home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1996 February / EnigmA AMIGA RUN 04 (1996)(G.R. Edizioni)(IT)[!][issue 1996-02][Skylink CD III].iso / earcd / comm2 / termsorc.lha / Extras / Source / term-source.lha / termConsole.c < prev    next >
C/C++ Source or Header  |  1995-09-26  |  58KB  |  3,480 lines

  1. /*
  2. **    termConsole.c
  3. **
  4. **    High-level terminal console routines
  5. **
  6. **    Copyright © 1990-1995 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. */
  9.  
  10. #include "termGlobal.h"
  11.  
  12.     /* Character set modes. */
  13.  
  14. enum    {    MODE_STANDARD,MODE_GFX };
  15.  
  16.     /* Hints for the data flow scanner. */
  17.  
  18. STATIC WORD        ScanStart,
  19.             ScanEnd;
  20.  
  21. STATIC WORD __far    AttentionCount[SCAN_COUNT],
  22.             AttentionLength[SCAN_COUNT],
  23.             FlowCount;
  24.  
  25.     /* Temporary console working buffer. */
  26.  
  27. STATIC UBYTE __far    ConTempBuffer[512];
  28.  
  29.     /* ConTranslateSetup():
  30.      *
  31.      *    Set up for buffer translation.
  32.      */
  33.  
  34. STATIC VOID __inline
  35. ConTranslateSetup(struct TranslationHandle *Handle,STRPTR SourceBuffer,LONG SourceLen,STRPTR DestinationBuffer,LONG DestinationLen,struct TranslationEntry **Table)
  36. {
  37.     Handle -> LocalBuffer        = NULL;
  38.     Handle -> LocalLen        = 0;
  39.  
  40.     Handle -> SourceBuffer        = SourceBuffer;
  41.     Handle -> SourceLen        = SourceLen;
  42.  
  43.     Handle -> DestinationBuffer    = DestinationBuffer;
  44.     Handle -> DestinationLen    = DestinationLen;
  45.  
  46.     Handle -> Table            = Table;
  47. }
  48.  
  49.     /* ConTranslateBuffer(struct TranslationHandle *Handle):
  50.      *
  51.      *    Translate buffer contents according to
  52.      *    translation table contents.
  53.      */
  54.  
  55. STATIC LONG __inline
  56. ConTranslateBuffer(struct TranslationHandle *Handle)
  57. {
  58.     register STRPTR                 Data        = Handle -> DestinationBuffer;
  59.     register LONG                 BytesWritten    = 0;
  60.     register struct TranslationEntry    *Entry;
  61.  
  62.         /* Are we to return any translated data? */
  63.  
  64.     while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  65.     {
  66.             /* Decrement number of bytes in buffer. */
  67.  
  68.         Handle -> LocalLen--;
  69.  
  70.             /* Return next character. */
  71.  
  72.         *Data++ = *Handle -> LocalBuffer++;
  73.  
  74.             /* Add another byte. */
  75.  
  76.         BytesWritten++;
  77.     }
  78.  
  79.         /* Loop until done. */
  80.  
  81.     while(Handle -> SourceLen && BytesWritten < Handle -> DestinationLen)
  82.     {
  83.             /* Another byte eaten. */
  84.  
  85.         Handle -> SourceLen--;
  86.  
  87.             /* Get table entry. */
  88.  
  89.         if(Entry = Handle -> Table[*Handle -> SourceBuffer++])
  90.         {
  91.                 /* Copy to local data area. */
  92.  
  93.             Handle -> LocalBuffer    = Entry -> String;
  94.             Handle -> LocalLen    = Entry -> Len;
  95.  
  96.                 /* Translate the data. */
  97.  
  98.             while(Handle -> LocalLen && BytesWritten < Handle -> DestinationLen)
  99.             {
  100.                     /* Decrement number of bytes in buffer. */
  101.  
  102.                 Handle -> LocalLen--;
  103.  
  104.                     /* Return next character. */
  105.  
  106.                 *Data++ = *Handle -> LocalBuffer++;
  107.  
  108.                     /* Add another byte. */
  109.  
  110.                 BytesWritten++;
  111.             }
  112.         }
  113.     }
  114.  
  115.     return(BytesWritten);
  116. }
  117.  
  118.     /* TrapFilter(register STRPTR Data,register LONG Size):
  119.      *
  120.      *    Handle the trap list, similar to FlowFilter().
  121.      */
  122.  
  123. STATIC VOID __regargs
  124. TrapFilter(register STRPTR Data,register LONG Size)
  125. {
  126.     STATIC LONG WaitCount = 0;
  127.  
  128.     struct List    *List = (struct List *)&GenericListTable[GLIST_TRAP] -> ListHeader;
  129.     struct TrapNode    *Node;
  130.  
  131.     register UBYTE c,Mask;
  132.  
  133.     ObtainSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  134.  
  135.     if(Config -> SerialConfig -> StripBit8)
  136.         Mask = 0x7F;
  137.     else
  138.         Mask = 0xFF;
  139.  
  140.     do
  141.     {
  142.         register BOOLEAN MatchMade;
  143.  
  144.         c = (*Data++) & Mask;
  145.  
  146.         do
  147.         {
  148.             MatchMade = FALSE;
  149.  
  150.             for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  151.             {
  152.                 if(Node -> Count == WaitCount)
  153.                 {
  154.                     if(c == (Node -> Sequence[WaitCount] & Mask))
  155.                     {
  156.                         MatchMade = TRUE;
  157.  
  158.                         if(++Node -> Count == Node -> SequenceLen)
  159.                         {
  160.                             struct DataMsg *Msg;
  161.  
  162.                             Node -> Count = 0;
  163.  
  164.                             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + strlen(Node -> Command) + 1))
  165.                             {
  166.                                 Msg -> Type = DATAMSGTYPE_SERIALCOMMAND;
  167.                                 Msg -> Data = (STRPTR)(Msg + 1);
  168.  
  169.                                 strcpy(Msg -> Data,Node -> Command);
  170.  
  171.                                 PutMsgItem(SpecialQueue,(struct MsgItem *)Msg);
  172.                             }
  173.                         }
  174.                     }
  175.                 }
  176.             }
  177.  
  178.             if(MatchMade)
  179.                 WaitCount++;
  180.             else
  181.             {
  182.                 if(WaitCount)
  183.                 {
  184.                     WaitCount = 0;
  185.  
  186.                     for(Node = (struct TrapNode *)List -> lh_Head ; Node -> Node . ln_Succ ; Node = (struct TrapNode *)Node -> Node . ln_Succ)
  187.                         Node -> Count = 0;
  188.                 }
  189.                 else
  190.                     break;
  191.             }
  192.         }
  193.         while(!WaitCount);
  194.     }
  195.     while(--Size);
  196.  
  197.     ReleaseSemaphore(&GenericListTable[GLIST_TRAP] -> ListSemaphore);
  198. }
  199.  
  200.     /* FlowFilter(register STRPTR Data,register LONG Size,UBYTE Mask):
  201.      *
  202.      *    Data flow filter.
  203.      */
  204.  
  205. STATIC VOID __regargs
  206. FlowFilter(register STRPTR Data,register LONG Size,register UBYTE Mask)
  207. {
  208.     register UBYTE c;
  209.  
  210.         /* Run until done. */
  211.  
  212.     do
  213.     {
  214.         if(c = (*Data++ & Mask))
  215.         {
  216.  
  217.                 /* We already got a `CONNECT',
  218.                  * Continue scanning the serial output
  219.                  * data for the actual baud rate.
  220.                  */
  221.  
  222.             if(BaudPending)
  223.             {
  224.                 if(c < ' ')
  225.                 {
  226.                     while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  227.                         BaudCount--;
  228.  
  229.                     BaudBuffer[BaudCount] = 0;
  230.  
  231.                     FlowInfo . Connect = TRUE;
  232.                     FlowInfo . Changed = TRUE;
  233.  
  234.                     BaudPending = FALSE;
  235.  
  236.                     DTERate = GetBaudRate(BaudBuffer);
  237.  
  238.                     if(Quiet && Size > 1)
  239.                     {
  240.                         DataHold = Data;
  241.                         DataSize = Size - 1;
  242.                     }
  243.                 }
  244.                 else
  245.                 {
  246.                     if(BaudCount || c != ' ')
  247.                     {
  248.                         BaudBuffer[BaudCount++] = c;
  249.  
  250.                         if(BaudCount == 79)
  251.                         {
  252.                             while(BaudCount > 0 && BaudBuffer[BaudCount - 1] == ' ')
  253.                                 BaudCount--;
  254.  
  255.                             BaudBuffer[BaudCount] = 0;
  256.  
  257.                             FlowInfo . Connect = TRUE;
  258.                             FlowInfo . Changed = TRUE;
  259.  
  260.                             BaudPending = FALSE;
  261.  
  262.                             DTERate = GetBaudRate(BaudBuffer);
  263.  
  264.                             if(Quiet && Size > 1)
  265.                             {
  266.                                 DataHold = Data;
  267.                                 DataSize = Size - 1;
  268.                             }
  269.                         }
  270.                     }
  271.                 }
  272.             }
  273.             else
  274.             {
  275.                 register BYTE MatchMade;
  276.                 register WORD i;
  277.  
  278.                 do
  279.                 {
  280.                     MatchMade = FALSE;
  281.  
  282.                         /* Scan all ID strings for matches. */
  283.  
  284.                     for(i = ScanStart ; i <= ScanEnd ; i++)
  285.                     {
  286.                             /* This sequence is a likely
  287.                              * match.
  288.                              */
  289.  
  290.                         if(AttentionCount[i] == FlowCount)
  291.                         {
  292.                                 /* Does the character
  293.                                  * fit into the sequence?
  294.                                  */
  295.  
  296.                             if(c == AttentionBuffers[i][FlowCount] & Mask)
  297.                             {
  298.                                 MatchMade = TRUE;
  299.  
  300.                                     /* Did we hit the
  301.                                      * last character
  302.                                      * in the sequence?
  303.                                      */
  304.  
  305.                                 if(++AttentionCount[i] == AttentionLength[i])
  306.                                 {
  307.                                         /* We've got a valid
  308.                                          * sequence, now look
  309.                                          * which flags to change.
  310.                                          */
  311.  
  312.                                     switch(i)
  313.                                     {
  314.                                             /* We got a `no carrier' message. */
  315.  
  316.                                         case SCAN_NOCARRIER:
  317.  
  318.                                             if(!FlowInfo . NoCarrier)
  319.                                             {
  320.                                                 FlowInfo . NoCarrier    = TRUE;
  321.                                                 FlowInfo . Changed    = TRUE;
  322.                                             }
  323.  
  324.                                             break;
  325.  
  326.                                             /* Got another call. */
  327.  
  328.                                         case SCAN_RING:
  329.  
  330.                                             if(!FlowInfo . Ring)
  331.                                             {
  332.                                                 FlowInfo . Ring        = TRUE;
  333.                                                 FlowInfo . Changed    = TRUE;
  334.                                             }
  335.  
  336.                                             break;
  337.  
  338.                                             /* Got a voice call. */
  339.  
  340.                                         case SCAN_VOICE:
  341.  
  342.                                             if(!FlowInfo . Voice)
  343.                                             {
  344.                                                 FlowInfo . Voice    = TRUE;
  345.                                                 FlowInfo . Changed    = TRUE;
  346.                                             }
  347.  
  348.                                             break;
  349.  
  350.                                             /* Modem reported an error. */
  351.  
  352.                                         case SCAN_ERROR:
  353.  
  354.                                             if(!FlowInfo . Error)
  355.                                             {
  356.                                                 FlowInfo . Error    = TRUE;
  357.                                                 FlowInfo . Changed    = TRUE;
  358.                                             }
  359.  
  360.                                             break;
  361.  
  362.                                             /* Got a connect message. */
  363.  
  364.                                         case SCAN_CONNECT:
  365.  
  366.                                             ObtainSemaphore(&OnlineSemaphore);
  367.  
  368.                                             if(!Online)
  369.                                             {
  370.                                                 BaudBuffer[0]    = 0;
  371.  
  372.                                                 BaudPending    = TRUE;
  373.                                                 BaudCount    = 0;
  374.                                             }
  375.  
  376.                                             ReleaseSemaphore(&OnlineSemaphore);
  377.  
  378.                                             break;
  379.  
  380.                                             /* Line is busy. */
  381.  
  382.                                         case SCAN_BUSY:
  383.  
  384.                                             if(!FlowInfo . Busy)
  385.                                             {
  386.                                                 FlowInfo . Busy        = TRUE;
  387.                                                 FlowInfo . Changed    = TRUE;
  388.                                             }
  389.  
  390.                                             break;
  391.  
  392.                                         case SCAN_NODIALTONE:
  393.  
  394.                                             if(!FlowInfo . NoDialTone)
  395.                                             {
  396.                                                 FlowInfo . NoDialTone    = TRUE;
  397.                                                 FlowInfo . Changed    = TRUE;
  398.                                             }
  399.  
  400.                                             break;
  401.  
  402.                                             /* Modem accepted a command. */
  403.  
  404.                                         case SCAN_OK:
  405.  
  406.                                             if(!FlowInfo . Ok)
  407.                                             {
  408.                                                 FlowInfo . Ok        = TRUE;
  409.                                                 FlowInfo . Changed    = TRUE;
  410.                                             }
  411.  
  412.                                             break;
  413.  
  414.                                         default:
  415.  
  416.                                             if(!FlowInfo . Signature)
  417.                                             {
  418.                                                 FlowInfo . Signature    = i;
  419.                                                 FlowInfo . Changed    = TRUE;
  420.                                             }
  421.  
  422.                                             break;
  423.                                     }
  424.                                 }
  425.                             }
  426.                         }
  427.                     }
  428.  
  429.                     if(MatchMade)
  430.                         FlowCount++;
  431.                     else
  432.                     {
  433.                         if(FlowCount)
  434.                         {
  435.                             FlowCount = 0;
  436.  
  437.                             memset(AttentionCount,0,sizeof(AttentionCount));
  438.                         }
  439.                         else
  440.                             break;
  441.                     }
  442.                 }
  443.                 while(!FlowCount);
  444.             }
  445.         }
  446.     }
  447.     while(--Size);
  448. }
  449.  
  450.     /* StripSequence():
  451.      *
  452.      *    Strips a string from ESC and CSI introduced control
  453.      *    sequences.
  454.      */
  455.  
  456. STATIC LONG __regargs
  457. StripSequence(STRPTR Src,STRPTR Dst,LONG Length)
  458. {
  459.     STATIC BYTE    HasESC    = FALSE,
  460.             HasCSI    = FALSE;
  461.     LONG        Size    = 0;
  462.  
  463.     while(Length--)
  464.     {
  465.         if(HasESC)
  466.         {
  467.             if(*Src == '[')
  468.             {
  469.                 HasESC = FALSE;
  470.                 HasCSI = TRUE;
  471.             }
  472.             else
  473.             {
  474.                 if(*Src >= '0')
  475.                     HasESC = FALSE;
  476.             }
  477.  
  478.             Src++;
  479.  
  480.             continue;
  481.         }
  482.  
  483.         if(HasCSI)
  484.         {
  485.             if(*Src >= '@')
  486.                 HasCSI = FALSE;
  487.  
  488.             Src++;
  489.  
  490.             continue;
  491.         }
  492.  
  493.         switch(*Src)
  494.         {
  495.             case CAN:
  496.             case SUB:
  497.  
  498.                 HasESC = HasCSI = FALSE;
  499.                 break;
  500.  
  501.             case '\r':
  502.  
  503.                 break;
  504.  
  505.             case ESC:
  506.  
  507.                 HasESC = TRUE;
  508.                 break;
  509.  
  510.             case CSI:
  511.  
  512.                 HasCSI = TRUE;
  513.                 break;
  514.  
  515.             default:
  516.  
  517.                 if(IsPrintable[*Src])
  518.                 {
  519.                     *Dst++ = *Src;
  520.  
  521.                     Size++;
  522.                 }
  523.  
  524.                 break;
  525.         }
  526.  
  527.         Src++;
  528.     }
  529.  
  530.     return(Size);
  531. }
  532.  
  533.     /* ConOutputPrinter(STRPTR Buffer,LONG Size):
  534.      *
  535.      *    Raw text output routine, printer capture flavour.
  536.      */
  537.  
  538. STATIC VOID
  539. ConOutputPrinter(STRPTR Buffer,LONG Size)
  540. {
  541.     if(FWrite(PrinterCapture,Buffer,Size,1) != 1)
  542.     {
  543.         BlockWindows();
  544.  
  545.         if(!MyEasyRequest(NULL,LocaleString(MSG_CONSOLE_ERROR_WRITING_TO_PRINTER_TXT),LocaleString(MSG_CONSOLE_IGNORE_CLOSE_PRINTER_TXT)))
  546.             ClosePrinterCapture(TRUE);
  547.  
  548.         ReleaseWindows();
  549.     }
  550. }
  551.  
  552.     /* ConOutputGFX(STRPTR Buffer,LONG Size):
  553.      *
  554.      *    Raw text output routine, GFX text flavour.
  555.      */
  556.  
  557. STATIC VOID
  558. ConOutputGFX(STRPTR Buffer,LONG Size)
  559. {
  560.     register WORD Offset;
  561.  
  562.         /* Do we still have a character in the
  563.          * magnificient buffer?
  564.          */
  565.  
  566.     while(Size)
  567.     {
  568.             /* Cursor is positioned at
  569.              * the right hand side of the
  570.              * display. If auto-wrap is
  571.              * enabled, perform some
  572.              * kind of CR/LF, else leave
  573.              * the cursor where it is and
  574.              * quit the show.
  575.              */
  576.  
  577.         if(CursorX > LastPrintableColumn)
  578.         {
  579.                 /* Wrap cursor. */
  580.  
  581.             if(Config -> EmulationConfig -> LineWrap)
  582.             {
  583.                     /* Move to beginning of next line. */
  584.  
  585.                 CursorX = 0;
  586.  
  587.                 DownLine();
  588.  
  589.                     /* Reposition cursor, don't redraw it. */
  590.  
  591.                 RepositionCursor();
  592.             }
  593.             else
  594.             {
  595.                     /* Stop the cursor. */
  596.  
  597.                 CursorX = LastPrintableColumn;
  598.  
  599.                     /* Make it reappear. */
  600.  
  601.                 RepositionCursor();
  602.  
  603.                 return;
  604.             }
  605.         }
  606.  
  607.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  608.             Offset = Size;
  609.  
  610.         if(Config -> EmulationConfig -> InsertMode)
  611.         {
  612.             RasterShiftChar(Offset);
  613.  
  614.             ScrollLineShiftChar(Offset);
  615.  
  616.             ShiftChar(Offset);
  617.         }
  618.  
  619.         RasterPutString(Buffer,Offset);
  620.  
  621.         ScrollLinePutString(Offset);
  622.  
  623.         if(FontScalingRequired)
  624.             PrintScaled(Buffer,Offset,CurrentFontScale);
  625.         else
  626.             GfxText(RPort,Buffer,Offset);
  627.  
  628.         Buffer    += Offset;
  629.  
  630.         Size    -= Offset;
  631.  
  632.         CursorX    += Offset;
  633.     }
  634.  
  635.     RepositionCursor();
  636. }
  637.  
  638.     /* ConOutputNormal(STRPTR Buffer,LONG Size):
  639.      *
  640.      *    Raw text output routine, normal text flavour.
  641.      */
  642.  
  643. STATIC VOID
  644. ConOutputNormal(STRPTR Buffer,LONG Size)
  645. {
  646.     register WORD Offset;
  647.  
  648.     while(Size)
  649.     {
  650.         if(CursorX > LastPrintableColumn)
  651.         {
  652.             if(Config -> EmulationConfig -> LineWrap)
  653.             {
  654.                 CursorX = 0;
  655.  
  656.                 DownLine();
  657.  
  658.                 RepositionCursor();
  659.             }
  660.             else
  661.             {
  662.                 CursorX = LastPrintableColumn;
  663.  
  664.                 RepositionCursor();
  665.  
  666.                 return;
  667.             }
  668.         }
  669.  
  670.         if((Offset = LastPrintableColumn + 1 - CursorX) > Size)
  671.             Offset = Size;
  672.  
  673.         if(Config -> EmulationConfig -> InsertMode)
  674.         {
  675.             RasterShiftChar(Offset);
  676.  
  677.             ScrollLineShiftChar(Offset);
  678.  
  679.             ShiftChar(Offset);
  680.         }
  681.  
  682.         RasterPutString(Buffer,Offset);
  683.  
  684.         ScrollLinePutString(Offset);
  685.  
  686.         if(FontScalingRequired)
  687.             PrintScaled(Buffer,Offset,CurrentFontScale);
  688.         else
  689.             Text(RPort,Buffer,Offset);
  690.  
  691.         Buffer    += Offset;
  692.  
  693.         Size    -= Offset;
  694.  
  695.         CursorX    += Offset;
  696.     }
  697.  
  698.     RepositionCursor();
  699. }
  700.  
  701.     /* ConProcessUpdate():
  702.      *
  703.      *    Choose the right console data processing routine.
  704.      */
  705.  
  706. VOID
  707. ConProcessUpdate(VOID)
  708. {
  709.     Forbid();
  710.  
  711.     if(XEmulatorBase && Config -> TerminalConfig -> EmulationMode == EMULATION_EXTERNAL)
  712.     {
  713.         if(ReceiveTable)
  714.             ConProcessData = ConProcessDataTransExternal;
  715.         else
  716.             ConProcessData = ConProcessDataExternal;
  717.     }
  718.     else
  719.     {
  720.         if(Config -> SerialConfig -> StripBit8)
  721.         {
  722.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  723.                 ConProcessData = ConProcessDataHex7;
  724.             else
  725.                 ConProcessData = ConProcessData7;
  726.         }
  727.         else
  728.         {
  729.             if(Config -> TerminalConfig -> EmulationMode == EMULATION_HEX)
  730.                 ConProcessData = ConProcessDataHex8;
  731.             else
  732.                 ConProcessData = ConProcessData8;
  733.         }
  734.     }
  735.  
  736.     Permit();
  737. }
  738.  
  739.     /* ConOutputUpdate():
  740.      *
  741.      *    Choose the right raw text output routine for the job.
  742.      */
  743.  
  744. VOID
  745. ConOutputUpdate()
  746. {
  747.     Forbid();
  748.  
  749.     if(Config -> CaptureConfig -> BufferMode == BUFFERMODE_FLOW)
  750.         SaveRaster = SaveRasterDummy;
  751.     else
  752.         SaveRaster = SaveRasterReal;
  753.  
  754.     if(BufferFrozen || Config -> CaptureConfig -> BufferMode != BUFFERMODE_FLOW)
  755.     {
  756.         if(FileCapture)
  757.         {
  758.             if(PrinterCapture)
  759.             {
  760.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  761.                     CaptureData = CaptureFilteredTo_File_Printer;
  762.                 else
  763.                     CaptureData = CaptureRawTo_File_Printer;
  764.             }
  765.             else
  766.             {
  767.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  768.                     CaptureData = CaptureFilteredTo_File;
  769.                 else
  770.                     CaptureData = CaptureRawTo_File;
  771.             }
  772.         }
  773.         else
  774.         {
  775.             if(PrinterCapture)
  776.             {
  777.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  778.                     CaptureData = CaptureFilteredTo_Printer;
  779.                 else
  780.                     CaptureData = CaptureRawTo_Printer;
  781.             }
  782.             else
  783.                 CaptureData = NULL;
  784.         }
  785.     }
  786.     else
  787.     {
  788.         if(FileCapture)
  789.         {
  790.             if(PrinterCapture)
  791.             {
  792.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  793.                     CaptureData = CaptureFilteredTo_Buffer_File_Printer;
  794.                 else
  795.                     CaptureData = CaptureRawTo_Buffer_File_Printer;
  796.             }
  797.             else
  798.             {
  799.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  800.                     CaptureData = CaptureFilteredTo_Buffer_File;
  801.                 else
  802.                     CaptureData = CaptureRawTo_Buffer_File;
  803.             }
  804.         }
  805.         else
  806.         {
  807.             if(PrinterCapture)
  808.             {
  809.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  810.                     CaptureData = CaptureFilteredTo_Buffer_Printer;
  811.                 else
  812.                     CaptureData = CaptureRawTo_Buffer_Printer;
  813.             }
  814.             else
  815.             {
  816.                 if(Config -> CaptureConfig -> CaptureFilterMode && !RawCapture)
  817.                     CaptureData = CaptureFilteredTo_Buffer;
  818.                 else
  819.                     CaptureData = CaptureRawTo_Buffer;
  820.             }
  821.         }
  822.     }
  823.  
  824.     if(ControllerActive)
  825.         ConOutput = ConOutputPrinter;
  826.     else
  827.     {
  828.         if(CurrentFont == GFX)
  829.             ConOutput = ConOutputGFX;
  830.         else
  831.             ConOutput = ConOutputNormal;
  832.     }
  833.  
  834.     if(ReceiveTable)
  835.         ConDump = ConTransWrite;
  836.     else
  837.         ConDump = ConOutput;
  838.  
  839.     Permit();
  840. }
  841.  
  842.     /* ConFontScaleUpdate():
  843.      *
  844.      *    Choose the right font scale for the job.
  845.      */
  846.  
  847. VOID
  848. ConFontScaleUpdate()
  849. {
  850.     CurrentFontScale    = RasterAttr[CursorY];
  851.     FontScalingRequired    = FALSE;
  852.     CharCellNominator    = 1;
  853.  
  854.     if(CurrentCharWidth == SCALE_HALF)
  855.         CharCellDenominator = 2;
  856.     else
  857.         CharCellDenominator = 1;
  858.  
  859.     if(CurrentFontScale == SCALE_ATTR_NORMAL)
  860.     {
  861.         if(CurrentCharWidth == SCALE_HALF)
  862.         {
  863.                 // Half of normal width
  864.  
  865.             LastPrintableColumn    = (LastColumn + 1) * 2 - 1;
  866.             LastPrintablePixel     = (LastPixel + 1) * 2 - 1;
  867.             FontScalingRequired    = TRUE;
  868.         }
  869.         else
  870.         {
  871.                 // Normal width
  872.  
  873.             LastPrintableColumn    = LastColumn;
  874.             LastPrintablePixel    = LastPixel;
  875.         }
  876.     }
  877.     else
  878.     {
  879.         if(CurrentCharWidth == SCALE_HALF)
  880.         {
  881.                 // Half of double width
  882.  
  883.             LastPrintableColumn    = LastColumn;
  884.             LastPrintablePixel    = LastPixel;
  885.         }
  886.         else
  887.         {
  888.                 // Double width
  889.  
  890.             LastPrintableColumn    = ((LastColumn + 1) / 2) - 1;
  891.             LastPrintablePixel    = ((LastPixel + 1) / 2) - 1;
  892.             FontScalingRequired    = TRUE;
  893.         }
  894.     }
  895. }
  896.  
  897.     /* ConTransWrite(STRPTR Buffer,LONG Size):
  898.      *
  899.      *    Frontend for ConWrite(), including character translation.
  900.      */
  901.  
  902. VOID
  903. ConTransWrite(STRPTR Buffer,LONG Size)
  904. {
  905.     struct TranslationHandle    Handle;
  906.     UBYTE                LocalBuffer[256];
  907.  
  908.         /* Set up for translation. */
  909.  
  910.     ConTranslateSetup(&Handle,Buffer,Size,LocalBuffer,256,ReceiveTable);
  911.  
  912.         /* Process and output the data. */
  913.  
  914.     while(Size = ConTranslateBuffer(&Handle))
  915.         (* ConOutput)(LocalBuffer,Size);
  916. }
  917.  
  918.     /* ConProcessDataTransExternal(register STRPTR String,register LONG Size):
  919.      *
  920.      *    Process data, external emulation including translation flavour.
  921.      */
  922.  
  923. VOID
  924. ConProcessDataTransExternal(register STRPTR String,register LONG Size)
  925. {
  926.     struct TranslationHandle Handle;
  927.  
  928.         /* Set up for translation. */
  929.  
  930.     ConTranslateSetup(&Handle,String,Size,ConTempBuffer,256,ReceiveTable);
  931.  
  932.     if(StripBuffer)
  933.     {
  934.         register LONG Len;
  935.  
  936.             /* Process and output the data. */
  937.  
  938.         while(Size = ConTranslateBuffer(&Handle))
  939.         {
  940.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  941.  
  942.             XEM_HostData . Source        = ConTempBuffer;
  943.             XEM_HostData . Destination    = StripBuffer;
  944.  
  945.             if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  946.             {
  947.                 if(CaptureData)
  948.                     (*CaptureData)(StripBuffer,Len);
  949.             }
  950.         }
  951.     }
  952.     else
  953.     {
  954.             /* Process and output the data. */
  955.  
  956.         while(Size = ConTranslateBuffer(&Handle))
  957.             XEmulatorWrite(XEM_IO,ConTempBuffer,Size);
  958.     }
  959. }
  960.  
  961.     /* ConProcessDataExternal(register STRPTR String,register LONG Size):
  962.      *
  963.      *    Process data, external emulation flavour.
  964.      */
  965.  
  966. VOID
  967. ConProcessDataExternal(register STRPTR String,register LONG Size)
  968. {
  969.     XEmulatorWrite(XEM_IO,String,Size);
  970.  
  971.         /* Build another string to contain
  972.          * the pure ASCII contents, i.e.
  973.          * not including any ESC control
  974.          * sequences.
  975.          */
  976.  
  977.     if(StripBuffer)
  978.     {
  979.         register LONG Len;
  980.  
  981.         XEM_HostData . Source        = String;
  982.         XEM_HostData . Destination    = StripBuffer;
  983.  
  984.         if(Len = XEmulatorHostMon(XEM_IO,&XEM_HostData,Size))
  985.         {
  986.             if(CaptureData)
  987.                 (*CaptureData)(StripBuffer,Len);
  988.         }
  989.     }
  990. }
  991.  
  992.     /* ConProcessData7(register STRPTR String,register LONG Size):
  993.      *
  994.      *    Process data, 7 bit flavour.
  995.      */
  996.  
  997. VOID
  998. ConProcessData7(register STRPTR String,register LONG Size)
  999. {
  1000.     register LONG    Len = 0;
  1001.     register UBYTE    c;
  1002.  
  1003. #if 0
  1004.         // Check for prescroll/jump scroll
  1005.  
  1006.     if(CursorY == Bottom && Bottom > 0)
  1007.     {
  1008.             // The maximum number of line feeds we need to look for
  1009.  
  1010.         register WORD Max = MAX(Config -> EmulationConfig -> MaxJump,Config -> EmulationConfig -> MaxScroll);
  1011.  
  1012.             // Any prescroll/jump scroll action wanted?
  1013.  
  1014.         if(Max)
  1015.         {
  1016.             register WORD     Count    = Size,
  1017.                      Lines    = 0;
  1018.             register UBYTE    *Buffer    = String;
  1019.  
  1020.                 // Count the number of line feeds
  1021.  
  1022.             while(Count--)
  1023.             {
  1024.                 if((*Buffer++ & 0x7F) == '\n')
  1025.                 {
  1026.                     if(++Lines == Max)
  1027.                         break;
  1028.                 }
  1029.             }
  1030.  
  1031.                 // Ok, so we have found something
  1032.  
  1033.             if(Lines)
  1034.             {
  1035.                 register WORD Scroll,TotalLines;
  1036.  
  1037.                     // Scroll by default?
  1038.  
  1039.                 if(Scroll = Config -> EmulationConfig -> MaxJump)
  1040.                 {
  1041.                         // If there is more, use it
  1042.  
  1043.                     if(Lines > Scroll)
  1044.                         Scroll = Lines;
  1045.                 }
  1046.                 else
  1047.                     Scroll = Lines;
  1048.  
  1049.                     // How tall is the current scroll region?
  1050.  
  1051.                 TotalLines = Bottom - Top + 1;
  1052.  
  1053.                     // Don't scroll more than the entire screenful
  1054.  
  1055.                 if(Scroll > TotalLines)
  1056.                     Scroll = TotalLines;
  1057.  
  1058.                     // Is it worth scrolling?
  1059.  
  1060.                 if(Scroll > 1)
  1061.                 {
  1062.                     LONG OldBack = BackgroundPen;
  1063.  
  1064.                     if(OldBack)
  1065.                     {
  1066.                         BackgroundPen = 0;
  1067.  
  1068.                         UpdatePens();
  1069.                     }
  1070.  
  1071.                         // Scroll the region...
  1072.  
  1073.                     ScrollRegion(Scroll);
  1074.  
  1075.                         // Reposition the cursor
  1076.  
  1077.                     if(CursorY > Scroll)
  1078.                         CursorY -= Scroll;
  1079.                     else
  1080.                         CursorY = 0;
  1081.  
  1082.                     RepositionCursor();
  1083.  
  1084.                     if(OldBack)
  1085.                     {
  1086.                         BackgroundPen = OldBack;
  1087.  
  1088.                         UpdatePens();
  1089.                     }
  1090.                 }
  1091.             }
  1092.         }
  1093.     }
  1094. #endif
  1095.  
  1096.         /* If still parsing a sequence,
  1097.          * continue with it.
  1098.          */
  1099.  
  1100.     if(InSequence)
  1101.     {
  1102.         while(Size--)
  1103.         {
  1104.             c = *String++ & 0x7F;
  1105.  
  1106.             if(!(*AbortTable[c])(c))
  1107.             {
  1108.                 InSequence = FALSE;
  1109.  
  1110.                 break;
  1111.             }
  1112.         }
  1113.     }
  1114.  
  1115.         /* Check which font we are in, if other than Topaz
  1116.          * the only invalid char is a Null (0) which will
  1117.          * display as a space if let to continue.
  1118.          */
  1119.  
  1120.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1121.     {
  1122.         while(Size-- > 0)
  1123.         {
  1124.             if(IsPrintable[c = *String++ & 0x7F])
  1125.             {
  1126.                     /* This character is associated with a
  1127.                      * special function (bell, xon, xoff, etc.).
  1128.                      */
  1129.  
  1130.                 if(SpecialTable[c])
  1131.                 {
  1132.                     if(Len)
  1133.                     {
  1134.                         (*ConDump)(ConTempBuffer,Len);
  1135.  
  1136.                         Len = 0;
  1137.                     }
  1138.  
  1139.                         /* Does this character start
  1140.                          * a control sequence?
  1141.                          */
  1142.  
  1143.                     if(InSequence = (*SpecialTable[c])(c))
  1144.                     {
  1145.                         while(Size-- > 0)
  1146.                         {
  1147.                             c = *String++ & 0x7F;
  1148.  
  1149.                             if(!(*AbortTable[c])(c))
  1150.                             {
  1151.                                 InSequence = FALSE;
  1152.  
  1153.                                 break;
  1154.                             }
  1155.                         }
  1156.                     }
  1157.                 }
  1158.                 else
  1159.                 {
  1160.                         /* Put the character into the buffer
  1161.                          * and flush it if necessary.
  1162.                          */
  1163.  
  1164.                     ConTempBuffer[Len] = c;
  1165.  
  1166.                     if(Len++ == 512)
  1167.                     {
  1168.                         (*ConDump)(ConTempBuffer,Len);
  1169.  
  1170.                         Len = 0;
  1171.                     }
  1172.                 }
  1173.             }
  1174.         }
  1175.     }
  1176.     else
  1177.     {
  1178.         while(Size-- > 0)
  1179.         {
  1180.             if(c = (*String++ & 0x7F))
  1181.             {
  1182.                     /* This character is associated with a
  1183.                      * special function (bell, xon, xoff, etc.).
  1184.                      */
  1185.  
  1186.                 if(SpecialTable[c])
  1187.                 {
  1188.                     if(Len)
  1189.                     {
  1190.                         (*ConDump)(ConTempBuffer,Len);
  1191.  
  1192.                         Len = 0;
  1193.                     }
  1194.  
  1195.                     if(InSequence = (*SpecialTable[c])(c))
  1196.                     {
  1197.                         while(Size-- > 0)
  1198.                         {
  1199.                             c = *String++ & 0x7F;
  1200.  
  1201.                             if(!(*AbortTable[c])(c))
  1202.                             {
  1203.                                 InSequence = FALSE;
  1204.  
  1205.                                 break;
  1206.                             }
  1207.                         }
  1208.                     }
  1209.                 }
  1210.                 else
  1211.                 {
  1212.                         /* Put the character into the buffer
  1213.                          * and flush it if necessary.
  1214.                          */
  1215.  
  1216.                     ConTempBuffer[Len] = c;
  1217.  
  1218.                     if(Len++ == 512)
  1219.                     {
  1220.                         (*ConDump)(ConTempBuffer,Len);
  1221.  
  1222.                         Len = 0;
  1223.                     }
  1224.                 }
  1225.             }
  1226.         }
  1227.     }
  1228.  
  1229.     if(Len)
  1230.         (*ConDump)(ConTempBuffer,Len);
  1231. }
  1232.  
  1233.     /* ConProcessData8(register STRPTR String,register LONG Size):
  1234.      *
  1235.      *    Process data, 8 bit flavour.
  1236.      */
  1237.  
  1238. VOID
  1239. ConProcessData8(register STRPTR String,register LONG Size)
  1240. {
  1241.     register LONG    Len = 0;
  1242.     register UBYTE    c;
  1243.  
  1244. #if 0
  1245.         // Check for prescroll/jump scroll
  1246.  
  1247.     if(CursorY == Bottom && Bottom > 0)
  1248.     {
  1249.             // The maximum number of line feeds we need to look for
  1250.  
  1251.         register WORD Max = MAX(Config -> EmulationConfig -> MaxJump,Config -> EmulationConfig -> MaxScroll);
  1252.  
  1253.             // Any prescroll/jump scroll action wanted?
  1254.  
  1255.         if(Max)
  1256.         {
  1257.             register WORD     Count    = Size,
  1258.                      Lines    = 0;
  1259.             register UBYTE    *Buffer    = String;
  1260.  
  1261.                 // Count the number of line feeds
  1262.  
  1263.             while(Count--)
  1264.             {
  1265.                 if(*Buffer++ == '\n')
  1266.                 {
  1267.                     if(++Lines == Max)
  1268.                         break;
  1269.                 }
  1270.             }
  1271.  
  1272.                 // Ok, so we have found something
  1273.  
  1274.             if(Lines)
  1275.             {
  1276.                 register WORD Scroll,TotalLines;
  1277.  
  1278.                     // Scroll by default?
  1279.  
  1280.                 if(Scroll = Config -> EmulationConfig -> MaxJump)
  1281.                 {
  1282.                         // If there is more, use it
  1283.  
  1284.                     if(Lines > Scroll)
  1285.                         Scroll = Lines;
  1286.                 }
  1287.                 else
  1288.                     Scroll = Lines;
  1289.  
  1290.                     // How tall is the current scroll region?
  1291.  
  1292.                 TotalLines = Bottom - Top + 1;
  1293.  
  1294.                     // Don't scroll more than the entire screenful
  1295.  
  1296.                 if(Scroll > TotalLines)
  1297.                     Scroll = TotalLines;
  1298.  
  1299.                     // Is it worth scrolling?
  1300.  
  1301.                 if(Scroll > 1)
  1302.                 {
  1303.                     LONG OldBack = BackgroundPen;
  1304.  
  1305.                     if(OldBack)
  1306.                     {
  1307.                         BackgroundPen = 0;
  1308.  
  1309.                         UpdatePens();
  1310.                     }
  1311.  
  1312.                         // Scroll the region...
  1313.  
  1314.                     ScrollRegion(Scroll);
  1315.  
  1316.                         // Reposition the cursor
  1317.  
  1318.                     if(CursorY > Scroll)
  1319.                         CursorY -= Scroll;
  1320.                     else
  1321.                         CursorY = 0;
  1322.  
  1323.                     RepositionCursor();
  1324.  
  1325.                     if(OldBack)
  1326.                     {
  1327.                         BackgroundPen = OldBack;
  1328.  
  1329.                         UpdatePens();
  1330.                     }
  1331.                 }
  1332.             }
  1333.         }
  1334.     }
  1335. #endif
  1336.  
  1337.     if(InSequence)
  1338.     {
  1339.         while(Size--)
  1340.         {
  1341.             c = *String++;
  1342.  
  1343.             if(!(*AbortTable[c])(c))
  1344.             {
  1345.                 InSequence = FALSE;
  1346.  
  1347.                 break;
  1348.             }
  1349.         }
  1350.     }
  1351.  
  1352.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1353.     {
  1354.         while(Size-- > 0)
  1355.         {
  1356.             if(IsPrintable[c = *String++])
  1357.             {
  1358.                 if(SpecialTable[c])
  1359.                 {
  1360.                     if(Len)
  1361.                     {
  1362.                         (*ConDump)(ConTempBuffer,Len);
  1363.  
  1364.                         Len = 0;
  1365.                     }
  1366.  
  1367.                     if(InSequence = (*SpecialTable[c])(c))
  1368.                     {
  1369.                         while(Size-- > 0)
  1370.                         {
  1371.                             c = *String++;
  1372.  
  1373.                             if(!(*AbortTable[c])(c))
  1374.                             {
  1375.                                 InSequence = FALSE;
  1376.  
  1377.                                 break;
  1378.                             }
  1379.                         }
  1380.                     }
  1381.                 }
  1382.                 else
  1383.                 {
  1384.                     ConTempBuffer[Len] = c;
  1385.  
  1386.                     if(Len++ == 512)
  1387.                     {
  1388.                         (*ConDump)(ConTempBuffer,Len);
  1389.  
  1390.                         Len = 0;
  1391.                     }
  1392.                 }
  1393.             }
  1394.         }
  1395.     }
  1396.     else
  1397.     {
  1398.         while(Size-- > 0)
  1399.         {
  1400.             if(c = *String++)
  1401.             {
  1402.                 if(SpecialTable[c])
  1403.                 {
  1404.                     if(Len)
  1405.                     {
  1406.                         (*ConDump)(ConTempBuffer,Len);
  1407.  
  1408.                         Len = 0;
  1409.                     }
  1410.  
  1411.                     if(InSequence = (*SpecialTable[c])(c))
  1412.                     {
  1413.                         while(Size-- > 0)
  1414.                         {
  1415.                             c = *String++;
  1416.  
  1417.                             if(!(*AbortTable[c])(c))
  1418.                             {
  1419.                                 InSequence = FALSE;
  1420.  
  1421.                                 break;
  1422.                             }
  1423.                         }
  1424.                     }
  1425.                 }
  1426.                 else
  1427.                 {
  1428.                     ConTempBuffer[Len] = c;
  1429.  
  1430.                     if(Len++ == 512)
  1431.                     {
  1432.                         (*ConDump)(ConTempBuffer,Len);
  1433.  
  1434.                         Len = 0;
  1435.                     }
  1436.                 }
  1437.             }
  1438.         }
  1439.     }
  1440.  
  1441.     if(Len)
  1442.         (*ConDump)(ConTempBuffer,Len);
  1443. }
  1444.  
  1445.     /* ConProcessDataHex7(register STRPTR String,register LONG Size):
  1446.      *
  1447.      *    Process data, hex mode flavour, seven bits.
  1448.      */
  1449.  
  1450. VOID
  1451. ConProcessDataHex7(register STRPTR String,register LONG Size)
  1452. {
  1453.     UBYTE    DummyBuffer[40],c;
  1454.     LONG    Fit,Spaces,Current;
  1455.  
  1456.         /* How many characters will fit into the line? */
  1457.  
  1458.     Fit    = (LastColumn + 1) / 4;
  1459.  
  1460.         /* Which position are we currently in? */
  1461.  
  1462.     Current    = CursorX / 3;
  1463.  
  1464.         /* Weird cursor position? */
  1465.  
  1466.     if(Current >= Fit || (CursorX % 3))
  1467.     {
  1468.         ConProcessData7("\r\n",2);
  1469.  
  1470.         Current = 0;
  1471.     }
  1472.  
  1473.         /* Check the font type. */
  1474.  
  1475.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1476.     {
  1477.         while(Size-- > 0)
  1478.         {
  1479.             c = (*String++) & 0x7F;
  1480.  
  1481.             Spaces = (Fit - Current) * 3 + Current - 3;
  1482.  
  1483.             if(c > ' ' && c < 127)
  1484.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1485.             else
  1486.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1487.  
  1488.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1489.  
  1490.             if(Current++ == Fit - 1)
  1491.             {
  1492.                 Current = 0;
  1493.  
  1494.                 ConProcessData7("\r\n",2);
  1495.             }
  1496.         }
  1497.     }
  1498.     else
  1499.     {
  1500.         while(Size-- > 0)
  1501.         {
  1502.             c = (*String++) & 0x7F;
  1503.  
  1504.             Spaces = (Fit - Current) * 3 + Current - 3;
  1505.  
  1506.             if(c && c != ' ')
  1507.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1508.             else
  1509.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1510.  
  1511.             ConProcessData7(DummyBuffer,strlen(DummyBuffer));
  1512.  
  1513.             if(Current++ == Fit - 1)
  1514.             {
  1515.                 Current = 0;
  1516.  
  1517.                 ConProcessData7("\r\n",2);
  1518.             }
  1519.         }
  1520.     }
  1521. }
  1522.  
  1523.     /* ConProcessDataHex8(register STRPTR String,register LONG Size):
  1524.      *
  1525.      *    Process data, hex mode flavour, eight bits.
  1526.      */
  1527.  
  1528. VOID
  1529. ConProcessDataHex8(register STRPTR String,register LONG Size)
  1530. {
  1531.     UBYTE    DummyBuffer[40],c;
  1532.     LONG    Fit,Spaces,Current;
  1533.  
  1534.         /* How many characters will fit into the line? */
  1535.  
  1536.     Fit    = (LastColumn + 1) / 4;
  1537.  
  1538.         /* Which position are we currently in? */
  1539.  
  1540.     Current    = CursorX / 3;
  1541.  
  1542.         /* Weird cursor position? */
  1543.  
  1544.     if(Current >= Fit || (CursorX % 3))
  1545.     {
  1546.         ConProcessData8("\r\n",2);
  1547.  
  1548.         Current = 0;
  1549.     }
  1550.  
  1551.         /* Check the font type. */
  1552.  
  1553.     if(Config -> TerminalConfig -> FontMode == FONT_STANDARD)
  1554.     {
  1555.         while(Size-- > 0)
  1556.         {
  1557.             c = *String++;
  1558.  
  1559.             Spaces = (Fit - Current) * 3 + Current - 3;
  1560.  
  1561.             if((c > ' ' && c < 127) || c > 160)
  1562.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1563.             else
  1564.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1565.  
  1566.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1567.  
  1568.             if(Current++ == Fit - 1)
  1569.             {
  1570.                 Current = 0;
  1571.  
  1572.                 ConProcessData8("\r\n",2);
  1573.             }
  1574.         }
  1575.     }
  1576.     else
  1577.     {
  1578.         while(Size-- > 0)
  1579.         {
  1580.             c = *String++;
  1581.  
  1582.             Spaces = (Fit - Current) * 3 + Current - 3;
  1583.  
  1584.             if(c && c != ' ')
  1585.                 SPrintf(DummyBuffer,"%02lx \33[%ldC%lc\33[%ldD",c,Spaces,c,Spaces + 1);
  1586.             else
  1587.                 SPrintf(DummyBuffer,"%02lx \33[%ldC.\33[%ldD",c,Spaces,Spaces + 1);
  1588.  
  1589.             ConProcessData8(DummyBuffer,strlen(DummyBuffer));
  1590.  
  1591.             if(Current++ == Fit - 1)
  1592.             {
  1593.                 Current = 0;
  1594.  
  1595.                 ConProcessData8("\r\n",2);
  1596.             }
  1597.         }
  1598.     }
  1599. }
  1600.  
  1601.     /* ConTransferHost(STRPTR Buffer,LONG Len):
  1602.      *
  1603.      *    Process data read from the serial line,
  1604.      *    special XPR flavour.
  1605.      */
  1606.  
  1607. VOID
  1608. ConTransferHost(STRPTR Buffer,LONG Len)
  1609. {
  1610.     Len = XProtocolHostMon(XprIO,Buffer,Len,SerialBufferSize);
  1611.  
  1612.     if(TransferWindow)
  1613.         TransferCleanup();
  1614.  
  1615.     if(Len)
  1616.         ConProcess(Buffer,Len);
  1617. }
  1618.  
  1619.     /* ConsoleCommand(STRPTR String):
  1620.      *
  1621.      *    Just like SerialCommand(), but addresses the local
  1622.      *    terminal side.
  1623.      */
  1624.  
  1625. VOID
  1626. ConsoleCommand(STRPTR String)
  1627. {
  1628.     STATIC UBYTE __far LocalBuffer[256];
  1629.  
  1630.     LONG    Count = 0,i,Len = strlen(String);
  1631.  
  1632.     BYTE    GotControl    = FALSE,
  1633.         GotEscape    = FALSE;
  1634.  
  1635.         /* Scan the string. */
  1636.  
  1637.     for(i = 0 ; i < Len ; i++)
  1638.     {
  1639.             /* We are looking for plain characters
  1640.              * and the control ('\') and escape
  1641.              * ('^') characters.
  1642.              */
  1643.  
  1644.         if(!GotControl && !GotEscape)
  1645.         {
  1646.                 /* Got a control character,
  1647.                  * the next byte will probably be
  1648.                  * a command sequence.
  1649.                  */
  1650.  
  1651.             if(String[i] == '\\')
  1652.             {
  1653.                 GotControl = TRUE;
  1654.  
  1655.                 continue;
  1656.             }
  1657.  
  1658.                 /* Got an escape character,
  1659.                  * the next byte will be some
  1660.                  * kind of control character
  1661.                  * (such as XON, XOF, bell, etc.).
  1662.                  */
  1663.  
  1664.             if(String[i] == '^')
  1665.             {
  1666.                 GotEscape = TRUE;
  1667.  
  1668.                 continue;
  1669.             }
  1670.  
  1671.                 /* This tells us to wait another
  1672.                  * second before continuing with
  1673.                  * the scanning.
  1674.                  */
  1675.  
  1676.             if(String[i] == '~')
  1677.                 continue;
  1678.  
  1679.                 /* Stuff the character into the
  1680.                  * buffer.
  1681.                  */
  1682.  
  1683.             LocalBuffer[Count++] = String[i];
  1684.         }
  1685.         else
  1686.         {
  1687.                 /* Convert the character to a control
  1688.                  * style character (^C, etc.).
  1689.                  */
  1690.  
  1691.             if(GotEscape)
  1692.             {
  1693.                 if(ToUpper(String[i]) >= 'A' && ToUpper(String[i]) <= '_')
  1694.                     LocalBuffer[Count++] = ToUpper(String[i]) - '@';
  1695.                 else
  1696.                     LocalBuffer[Count++] = String[i];
  1697.  
  1698.                 GotEscape = FALSE;
  1699.             }
  1700.  
  1701.                 /* The next character represents a command. */
  1702.  
  1703.             if(GotControl)
  1704.             {
  1705.                 switch(ToUpper(String[i]))
  1706.                 {
  1707.                         /* Translate code. */
  1708.  
  1709.                     case '*':
  1710.  
  1711.                         i++;
  1712.  
  1713.                         while(i < Len && String[i] == ' ')
  1714.                             i++;
  1715.  
  1716.                         if(i < Len)
  1717.                         {
  1718.                             UBYTE DummyBuffer[5],j = 0,Char;
  1719.  
  1720.                             if(String[i] >= '0' && String[i] <= '9')
  1721.                             {
  1722.                                 while(j < 3 && i < Len)
  1723.                                 {
  1724.                                     Char = String[i++];
  1725.  
  1726.                                     if(Char >= '0' && Char <= '9')
  1727.                                         DummyBuffer[j++] = Char;
  1728.                                     else
  1729.                                     {
  1730.                                         i--;
  1731.  
  1732.                                         break;
  1733.                                     }
  1734.                                 }
  1735.                             }
  1736.                             else
  1737.                             {
  1738.                                 while(j < 4 && i < Len)
  1739.                                 {
  1740.                                     Char = ToLower(String[i++]);
  1741.  
  1742.                                     if((Char >= '0' && Char <= '9') || (Char >= 'a' && Char <= 'z'))
  1743.                                         DummyBuffer[j++] = Char;
  1744.                                     else
  1745.                                     {
  1746.                                         i--;
  1747.  
  1748.                                         break;
  1749.                                     }
  1750.                                 }
  1751.                             }
  1752.  
  1753.                             DummyBuffer[j] = 0;
  1754.  
  1755.                             LocalBuffer[Count++] = NameToCode(DummyBuffer);
  1756.                         }
  1757.  
  1758.                         i--;
  1759.  
  1760.                         break;
  1761.  
  1762.                         /* Execute an AmigaDOS command. */
  1763.  
  1764.                     case 'D':
  1765.  
  1766.                         return;
  1767.  
  1768.                         /* Execute an ARexx command. */
  1769.  
  1770.                     case 'A':
  1771.  
  1772.                         return;
  1773.  
  1774.                         /* Add the control character ('\'). */
  1775.  
  1776.                     case '\\':
  1777.  
  1778.                         LocalBuffer[Count++] = '\\';
  1779.                         break;
  1780.  
  1781.                         /* This is a backspace. */
  1782.  
  1783.                     case 'B':
  1784.  
  1785.                         LocalBuffer[Count++] = '\b';
  1786.                         break;
  1787.  
  1788.                         /* This is a form feed. */
  1789.  
  1790.                     case 'F':
  1791.  
  1792.                         LocalBuffer[Count++] = '\f';
  1793.                         break;
  1794.  
  1795.                         /* This is a line feed. */
  1796.  
  1797.                     case 'N':
  1798.  
  1799.                         LocalBuffer[Count++] = '\n';
  1800.                         break;
  1801.  
  1802.                         /* Send the current password. */
  1803.  
  1804.                     case 'P':
  1805.  
  1806.                         break;
  1807.  
  1808.                         /* This is a carriage return. */
  1809.  
  1810.                     case 'R':
  1811.  
  1812.                         LocalBuffer[Count++] = '\r';
  1813.                         break;
  1814.  
  1815.                         /* This is a tab. */
  1816.  
  1817.                     case 'T':
  1818.  
  1819.                         LocalBuffer[Count++] = '\t';
  1820.                         break;
  1821.  
  1822.                         /* Send the current user name. */
  1823.  
  1824.                     case 'U':
  1825.  
  1826.                         break;
  1827.  
  1828.                         /* Send a break across the serial line. */
  1829.  
  1830.                     case 'X':
  1831.  
  1832.                         break;
  1833.  
  1834.                         /* Feed the contents of the
  1835.                          * clipboard into the input
  1836.                          * stream.
  1837.                          */
  1838.  
  1839.                     case 'I':
  1840.  
  1841.                         if(Count)
  1842.                             ConProcess(LocalBuffer,Count);
  1843.  
  1844.                         Count = LoadClip(LocalBuffer,256);
  1845.  
  1846.                         break;
  1847.  
  1848.                         /* Send a string to the clipboard. */
  1849.  
  1850.                     case 'G':
  1851.  
  1852.                         if(String[i + 1])
  1853.                             SaveClip(&String[i + 1],strlen(&String[i + 1]));
  1854.  
  1855.                         return;
  1856.  
  1857.                         /* Produce the escape character. */
  1858.  
  1859.                     case 'E':
  1860.  
  1861.                         LocalBuffer[Count++] = ESC;
  1862.                         break;
  1863.  
  1864.                         /* Call a menu item. */
  1865.  
  1866.                     case 'C':
  1867.  
  1868.                         break;
  1869.  
  1870.                         /* Stuff the character into the buffer. */
  1871.  
  1872.                     default:
  1873.  
  1874.                         LocalBuffer[Count++] = String[i];
  1875.                         break;
  1876.                 }
  1877.  
  1878.                 GotControl = FALSE;
  1879.             }
  1880.         }
  1881.  
  1882.             /* If the buffer is full, release it. */
  1883.  
  1884.         if(Count == 256)
  1885.         {
  1886.             ConProcess(LocalBuffer,Count);
  1887.  
  1888.             Count = 0;
  1889.         }
  1890.     }
  1891.  
  1892.     if(Count)
  1893.         ConProcess(LocalBuffer,Count);
  1894. }
  1895.  
  1896.     /* ConBypass(STRPTR String,LONG Size):
  1897.      *
  1898.      *    Bypass the `normal' ConOutput() data processing.
  1899.      */
  1900.  
  1901. VOID __regargs
  1902. ConBypass(STRPTR String,LONG Size)
  1903. {
  1904.     if(Size < 0)
  1905.         Size = strlen(String);
  1906.  
  1907.     if(Size > 0)
  1908.     {
  1909.         VOID (* ProcessData)(STRPTR,LONG);
  1910.  
  1911.         if(Config -> SerialConfig -> StripBit8)
  1912.             ProcessData = ConProcessData7;
  1913.         else
  1914.             ProcessData = ConProcessData8;
  1915.  
  1916.         ObtainSemaphore(&TerminalSemaphore);
  1917.  
  1918.         if(Marking)
  1919.             DropMarker();
  1920.  
  1921.         ClearCursor();
  1922.  
  1923.         (*ProcessData)(String,Size);
  1924.  
  1925.         DrawCursor();
  1926.  
  1927.         ReleaseSemaphore(&TerminalSemaphore);
  1928.     }
  1929. }
  1930.  
  1931.     /* ConProcess(STRPTR String,LONG Size):
  1932.      *
  1933.      *    Process the contents of a string to be sent to the
  1934.      *    console window.
  1935.      */
  1936.  
  1937. VOID
  1938. ConProcess(register STRPTR String,register LONG Size)
  1939. {
  1940.         /* Feed the flow filter. */
  1941.  
  1942.     if(UseFlow)
  1943.     {
  1944.         if(Config -> SerialConfig -> StripBit8)
  1945.             FlowFilter(String,Size,0x7F);
  1946.         else
  1947.             FlowFilter(String,Size,0xFF);
  1948.     }
  1949.  
  1950.         /* In quiet mode no characters are echoed to the
  1951.          * console window, they are just passed through
  1952.          * the data flow filter. Usually, this mode is
  1953.          * enabled by the dial panel.
  1954.          */
  1955.  
  1956.     if(!Quiet)
  1957.     {
  1958.             /* Capture the data. */
  1959.  
  1960.         if(CaptureData && Size > 0)
  1961.         {
  1962.             if(Config -> CaptureConfig -> ConvertChars && Config -> TerminalConfig -> FontMode != FONT_STANDARD)
  1963.             {
  1964.                 UBYTE     LocalBuffer[BUFFER_LINE_MAX];
  1965.  
  1966.                 UBYTE    *Src = String,
  1967.                     *Dst,
  1968.                      c;
  1969.  
  1970.                 ULONG     Count,Len = Size;
  1971.  
  1972.                 while(Len > 0)
  1973.                 {
  1974.                     Count = MIN(BUFFER_LINE_MAX,Len);
  1975.  
  1976.                     Len -= Count;
  1977.  
  1978.                     Dst = LocalBuffer;
  1979.  
  1980.                     do
  1981.                     {
  1982.                         if(c = ISOConversion[*Src++])
  1983.                             *Dst++ = c;
  1984.                         else
  1985.                             *Dst++ = (UBYTE)'·';
  1986.                     }
  1987.                     while(--Count > 0);
  1988.  
  1989.                     if((Count = (ULONG)Dst - (ULONG)&LocalBuffer[0]) > 0)
  1990.                         (*CaptureData)(LocalBuffer,Count);
  1991.                 }
  1992.             }
  1993.             else
  1994.                 (*CaptureData)(String,Size);
  1995.         }
  1996.  
  1997.             /* Remember the data. */
  1998.  
  1999.         if(RememberOutput)
  2000.             RememberOutputText(String,Size);
  2001.  
  2002.             /* Check the traps if necessary. */
  2003.  
  2004.         if(WatchTraps)
  2005.             TrapFilter(String,Size);
  2006.  
  2007.         if(Marking)
  2008.             DropMarker();
  2009.  
  2010.         if(TerminalQueue)
  2011.         {
  2012.             struct DataMsg *Msg;
  2013.  
  2014.             if(Msg = (struct DataMsg *)CreateMsgItem(sizeof(struct DataMsg) + Size))
  2015.             {
  2016.                 Msg -> Data = (APTR)(Msg + 1);
  2017.                 Msg -> Size = Size;
  2018.  
  2019.                 CopyMem(String,Msg -> Data,Msg -> Size);
  2020.  
  2021.                 PutMsgItem(TerminalQueue,Msg);
  2022.             }
  2023.             else
  2024.             {
  2025.                 ClearCursor();
  2026.  
  2027.                 (*ConProcessData)(String,Size);
  2028.  
  2029.                 DrawCursor();
  2030.             }
  2031.         }
  2032.         else
  2033.         {
  2034.             ClearCursor();
  2035.  
  2036.             (*ConProcessData)(String,Size);
  2037.  
  2038.             DrawCursor();
  2039.         }
  2040.     }
  2041. }
  2042.  
  2043.     /* ConWrites(STRPTR String,...):
  2044.      *
  2045.      *    Output a string to the console.
  2046.      */
  2047.  
  2048. VOID __stdargs
  2049. ConWrites(STRPTR String,...)
  2050. {
  2051.     va_list    VarArgs;
  2052.  
  2053.     if(Marking)
  2054.         DropMarker();
  2055.  
  2056.     va_start(VarArgs,String);
  2057.     VSPrintf(SharedBuffer,String,VarArgs);
  2058.     va_end(VarArgs);
  2059.  
  2060.     ConProcess(SharedBuffer,strlen(SharedBuffer));
  2061. }
  2062.  
  2063.     /* FlowInit():
  2064.      *
  2065.      *    Set up the data flow parser. The parser scans the serial
  2066.      *    output data for more or less interesting modem output
  2067.      *    (carrier lost, connect, etc.).
  2068.      */
  2069.  
  2070. VOID __regargs
  2071. FlowInit(BYTE FullReset)
  2072. {
  2073.     WORD i;
  2074.  
  2075.     for(i = 0 ; i < SCAN_COUNT ; i++)
  2076.         AttentionBuffers[i][0] = 0;
  2077.  
  2078.         /* Set up `NO CARRIER' message. */
  2079.  
  2080.     if(Config -> ModemConfig -> NoCarrier[0])
  2081.         SPrintf(AttentionBuffers[SCAN_NOCARRIER],"%s\r",Config -> ModemConfig -> NoCarrier);
  2082.  
  2083.         /* Set up ZRQINIT message. */
  2084.  
  2085. //    strcpy(AttentionBuffers[SCAN_ZMODEM],"*\030B01");
  2086.  
  2087.         /* Set up `CONNECT' message. */
  2088.  
  2089.     strcpy(AttentionBuffers[SCAN_CONNECT],Config -> ModemConfig -> Connect);
  2090.  
  2091.         /* Set up `VOICE' message. */
  2092.  
  2093.     if(Config -> ModemConfig -> Voice[0])
  2094.         SPrintf(AttentionBuffers[SCAN_VOICE],"%s\r",Config -> ModemConfig -> Voice);
  2095.  
  2096.         /* Set up `RING' message. */
  2097.  
  2098.     if(Config -> ModemConfig -> Ring[0])
  2099.         SPrintf(AttentionBuffers[SCAN_RING],"%s\r",Config -> ModemConfig -> Ring);
  2100.  
  2101.         /* Set up `BUSY' message. */
  2102.  
  2103.     if(Config -> ModemConfig -> Busy[0])
  2104.         SPrintf(AttentionBuffers[SCAN_BUSY],"%s\r",Config -> ModemConfig -> Busy);
  2105.  
  2106.         /* Set up `NO DIALTONE' message. */
  2107.  
  2108.     if(Config -> ModemConfig -> NoDialTone[0])
  2109.         SPrintf(AttentionBuffers[SCAN_NODIALTONE],"%s\r",Config -> ModemConfig -> NoDialTone);
  2110.  
  2111.         /* Set up `OK' message. */
  2112.  
  2113.     if(Config -> ModemConfig -> Ok[0])
  2114.         SPrintf(AttentionBuffers[SCAN_OK],"%s\r",Config -> ModemConfig -> Ok);
  2115.  
  2116.         /* Set up `ERROR' message. */
  2117.  
  2118.     if(Config -> ModemConfig -> Error[0])
  2119.         SPrintf(AttentionBuffers[SCAN_ERROR],"%s\r",Config -> ModemConfig -> Error);
  2120.  
  2121.         /* Reset match counter. */
  2122.  
  2123.     FlowCount = 0;
  2124.  
  2125.         /* Reset indices. */
  2126.  
  2127.     memset(AttentionCount,0,sizeof(AttentionCount));
  2128.  
  2129.         /* Determine lengths. */
  2130.  
  2131.     for(i = 0 ; i < SCAN_COUNT ; i++)
  2132.         AttentionLength[i] = strlen(AttentionBuffers[i]);
  2133.  
  2134.     for(i = SCAN_SIGDEFAULTUPLOAD ; i <= SCAN_SIGBINARYDOWNLOAD ; i++)
  2135.     {
  2136.         if(AttentionLength[i] = Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Length)
  2137.             memcpy(AttentionBuffers[i],Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Signature,Config -> TransferConfig -> Signatures[TRANSFERSIG_DEFAULTUPLOAD + i - SCAN_SIGDEFAULTUPLOAD] . Length);
  2138.     }
  2139.  
  2140.     if(Config -> TransferConfig -> ASCIIUploadType != XFER_XPR && Config -> TransferConfig -> ASCIIUploadType != XFER_EXTERNALPROGRAM)
  2141.         AttentionLength[SCAN_SIGASCIIUPLOAD] = 0;
  2142.  
  2143.     if(Config -> TransferConfig -> ASCIIDownloadType != XFER_XPR && Config -> TransferConfig -> ASCIIUploadType != XFER_EXTERNALPROGRAM)
  2144.         AttentionLength[SCAN_SIGASCIIDOWNLOAD] = 0;
  2145.  
  2146.     if(Config -> TransferConfig -> TextUploadType != XFER_XPR && Config -> TransferConfig -> TextUploadType != XFER_EXTERNALPROGRAM)
  2147.         AttentionLength[SCAN_SIGTEXTUPLOAD] = 0;
  2148.  
  2149.     if(Config -> TransferConfig -> TextDownloadType != XFER_XPR && Config -> TransferConfig -> TextUploadType != XFER_EXTERNALPROGRAM)
  2150.         AttentionLength[SCAN_SIGTEXTDOWNLOAD] = 0;
  2151.  
  2152.     if(Config -> TransferConfig -> BinaryUploadType != XFER_XPR && Config -> TransferConfig -> BinaryUploadType != XFER_EXTERNALPROGRAM)
  2153.         AttentionLength[SCAN_SIGBINARYUPLOAD] = 0;
  2154.  
  2155.     if(Config -> TransferConfig -> BinaryDownloadType != XFER_XPR && Config -> TransferConfig -> BinaryUploadType != XFER_EXTERNALPROGRAM)
  2156.         AttentionLength[SCAN_SIGBINARYDOWNLOAD] = 0;
  2157.  
  2158.     if(FullReset)
  2159.     {
  2160.             /* No, we are not yet looking for a baud rate. */
  2161.  
  2162.         BaudPending = FALSE;
  2163.  
  2164.             /* Reset the flags. */
  2165.  
  2166.         memset(&FlowInfo,FALSE,sizeof(struct FlowInfo));
  2167.     }
  2168.  
  2169.         /* Full data check is a lot slower than looking for
  2170.          * just a single sequence (such as the `CONNECT'
  2171.          * below). This mode is reserved for the dial panel.
  2172.          */
  2173.  
  2174.     ScanStart    = 0;
  2175.     ScanEnd        = SCAN_COUNT - 1;
  2176.     UseFlow        = TRUE;
  2177. }
  2178.  
  2179.     /* GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length):
  2180.      *
  2181.      *    Text output, if necessary switching from gfx font
  2182.      *    to current default font.
  2183.      */
  2184.  
  2185. VOID __regargs
  2186. GfxText(struct RastPort *RPort,STRPTR Buffer,LONG Length)
  2187. {
  2188.     BYTE TextMode;
  2189.     LONG SameMode;
  2190.  
  2191.         /* Determine current text rendering mode. */
  2192.  
  2193.     if(GfxTable[Buffer[0]] == MODE_GFX)
  2194.         TextMode = MODE_GFX;
  2195.     else
  2196.     {
  2197.         TextMode = MODE_STANDARD;
  2198.  
  2199.         SetFont(RPort,TextFont);
  2200.     }
  2201.  
  2202.         /* Reset number of characters in common mode. */
  2203.  
  2204.     SameMode = 0;
  2205.  
  2206.         /* Scan until all input is processed. */
  2207.  
  2208.     FOREVER
  2209.     {
  2210.             /* Scan for characters in the current mode. */
  2211.  
  2212.         while(GfxTable[Buffer[SameMode]] == TextMode && SameMode < Length)
  2213.             SameMode++;
  2214.  
  2215.             /* Output the text found. */
  2216.  
  2217.         Text(RPort,Buffer,SameMode);
  2218.  
  2219.             /* Decrement number of remaining bytes. */
  2220.  
  2221.         Length -= SameMode;
  2222.  
  2223.             /* Anything left? */
  2224.  
  2225.         if(Length)
  2226.         {
  2227.                 /* Skip to next character. */
  2228.  
  2229.             Buffer        += SameMode;
  2230.             SameMode     = 0;
  2231.  
  2232.                 /* Change text output mode. */
  2233.  
  2234.             if(TextMode == MODE_GFX)
  2235.             {
  2236.                 SetFont(RPort,TextFont);
  2237.  
  2238.                 TextMode = MODE_STANDARD;
  2239.             }
  2240.             else
  2241.             {
  2242.                 SetFont(RPort,GFX);
  2243.  
  2244.                 TextMode = MODE_GFX;
  2245.             }
  2246.         }
  2247.         else
  2248.             break;
  2249.     }
  2250.  
  2251.         /* Reset font type. */
  2252.  
  2253.     if(TextMode == MODE_STANDARD)
  2254.         SetFont(RPort,GFX);
  2255. }
  2256.  
  2257.     /* ConvertKey():
  2258.      *
  2259.      *    The actual key conversion routine.
  2260.      */
  2261.  
  2262. STATIC LONG __inline
  2263. ConvertKey(ULONG Qualifier,UWORD Code,ULONG Prev,STRPTR Buffer,LONG Len)
  2264. {
  2265.     LONG Actual;
  2266.  
  2267.         /* Fill in the defaults. */
  2268.  
  2269.     FakeInputEvent -> ie_Code        = Code;
  2270.     FakeInputEvent -> ie_Qualifier        = Qualifier;
  2271.     FakeInputEvent -> ie_position . ie_addr    = (APTR)Prev;
  2272.  
  2273.         /* Clear the buffer (sortof). */
  2274.  
  2275.     Buffer[0] = 0;
  2276.  
  2277.         /* Convert the codes. */
  2278.  
  2279.     if((Actual = RawKeyConvert(FakeInputEvent,Buffer,Len,KeyMap)) > 0)
  2280.         return(Actual);
  2281.     else
  2282.         return(0);
  2283. }
  2284.  
  2285.     /* ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev):
  2286.      *
  2287.      *    Much more simplified raw key conversion routine.
  2288.      */
  2289.  
  2290. UBYTE __regargs
  2291. ConvertTheKey(STRPTR Buffer,LONG *Len,UWORD Code,UWORD Qualifier,ULONG Prev)
  2292. {
  2293.     if(Buffer)
  2294.         Buffer[0] = 0;
  2295.  
  2296.     if(Len)
  2297.         *Len = 0;
  2298.  
  2299.         /* Key was pressed, not released. */
  2300.  
  2301.     if(!(Code & IECODE_UP_PREFIX))
  2302.     {
  2303.             /* These are the sequences mapped to special
  2304.              * control keys (cursor keys, function keys,
  2305.              * the help key).
  2306.              */
  2307.  
  2308.         STATIC struct { STRPTR RawCode; UBYTE Result; } ConversionTable[15] =
  2309.         {
  2310.             (STRPTR)"A",    CUP,
  2311.             (STRPTR)"B",    CDN,
  2312.             (STRPTR)"C",    CFW,
  2313.             (STRPTR)"D",    CBK,
  2314.  
  2315.             (STRPTR)"?~",    HLP,
  2316.  
  2317.             (STRPTR)"0~",    FN1,
  2318.             (STRPTR)"1~",    FN2,
  2319.             (STRPTR)"2~",    FN3,
  2320.             (STRPTR)"3~",    FN4,
  2321.             (STRPTR)"4~",    FN5,
  2322.             (STRPTR)"5~",    FN6,
  2323.             (STRPTR)"6~",    FN7,
  2324.             (STRPTR)"7~",    FN8,
  2325.             (STRPTR)"8~",    FN9,
  2326.             (STRPTR)"9~",    F10
  2327.         };
  2328.  
  2329.         STATIC UBYTE SeqLens[15] = { 1,1,1,1,2,2,2,2,2,2,2,2,2,2,2 };
  2330.  
  2331.         UBYTE    ConvertBuffer[257];
  2332.         LONG    Actual;
  2333.  
  2334.             /* If it's a function or cursor key, clear the qualifier. */
  2335.  
  2336.         if(Code >= CURSOR_UP_CODE && Code <= F10_CODE)
  2337.             Qualifier = NULL;
  2338.         else
  2339.         {
  2340.                 /* Does it have a numeric keypad qualifier set? */
  2341.  
  2342.             if((Qualifier & (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL)) == (IEQUALIFIER_NUMERICPAD | IEQUALIFIER_CONTROL))
  2343.             {
  2344.                 STRPTR String = NULL;
  2345.  
  2346.                     /* Look at the vanilla result. */
  2347.  
  2348.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_CONTROL | IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT | IEQUALIFIER_LALT | IEQUALIFIER_RALT),Code,Prev,ConvertBuffer,1))
  2349.                 {
  2350.                         /* Take a look at the results. */
  2351.  
  2352.                     switch(ConvertBuffer[0])
  2353.                     {
  2354.                         case '(':
  2355.                         case '[':
  2356.                         case '{':
  2357.  
  2358.                             String = "\033OP";
  2359.                             break;
  2360.  
  2361.                         case ')':
  2362.                         case ']':
  2363.                         case '}':
  2364.  
  2365.                             String = "\033OQ";
  2366.                             break;
  2367.  
  2368.                         case '/':
  2369.  
  2370.                             String = "\033OR";
  2371.                             break;
  2372.  
  2373.                         case '*':
  2374.  
  2375.                             String = "\033OS";
  2376.                             break;
  2377.  
  2378.                         default:
  2379.  
  2380.                             String = NULL;
  2381.                             break;
  2382.                     }
  2383.                 }
  2384.  
  2385.                 if(!String)
  2386.                 {
  2387.                     switch(Code)
  2388.                     {
  2389.                         case 0x5A:
  2390.  
  2391.                             String = "\033OP";
  2392.                             break;
  2393.  
  2394.                         case 0x5B:
  2395.  
  2396.                             String = "\033OQ";
  2397.                             break;
  2398.  
  2399.                         case 0x5C:
  2400.  
  2401.                             String = "\033OR";
  2402.                             break;
  2403.  
  2404.                         case 0x5D:
  2405.  
  2406.                             String = "\033OS";
  2407.                             break;
  2408.                     }
  2409.                 }
  2410.  
  2411.                     /* Return the PFx key code. */
  2412.  
  2413.                 if(String)
  2414.                 {
  2415.                     if(Buffer)
  2416.                         memcpy(Buffer,String,3);
  2417.  
  2418.                     if(Len)
  2419.                         *Len = 3;
  2420.  
  2421.                     return('\033');
  2422.                 }
  2423.             }
  2424.  
  2425.                 /* Does it have a shift qualifier set? */
  2426.  
  2427.             if(Qualifier & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT))
  2428.             {
  2429.                     /* Do the conversion... */
  2430.  
  2431.                 if(ConvertKey(Qualifier & ~(IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT),Code,Prev,ConvertBuffer,1))
  2432.                 {
  2433.                         /* Did it produce a tab key? If so, transfer
  2434.                          * Esc tab instead.
  2435.                          */
  2436.  
  2437.                     if(ConvertBuffer[0] == '\t')
  2438.                     {
  2439.                         if(Len)
  2440.                             *Len = 2;
  2441.  
  2442.                         if(Buffer)
  2443.                             memcpy(Buffer,"\033\t",2);
  2444.  
  2445.                         return('\033');
  2446.                     }
  2447.                 }
  2448.             }
  2449.  
  2450.                 /* Does it have the control qualifier set? */
  2451.  
  2452.             if(Qualifier & IEQUALIFIER_CONTROL)
  2453.             {
  2454.                     /* Do the conversion... */
  2455.  
  2456.                 if(ConvertKey(Qualifier & ~IEQUALIFIER_CONTROL,Code,Prev,ConvertBuffer,1))
  2457.                 {
  2458.                         /* Did it produce a space or an `at' sign? */
  2459.  
  2460.                     switch(ConvertBuffer[0])
  2461.                     {
  2462.                             /* NUL */
  2463.  
  2464.                         case ' ':
  2465.                         case '@':
  2466.                         case '2':
  2467.  
  2468.                             if(Len)
  2469.                                 *Len = 1;
  2470.  
  2471.                             if(Buffer)
  2472.                                 Buffer[0] = 0;
  2473.  
  2474.                             return(0);
  2475.  
  2476.                             /* Escape */
  2477.  
  2478.                         case '3':
  2479.                         case '[':
  2480.  
  2481.                             if(Len)
  2482.                                 *Len = 1;
  2483.  
  2484.                             if(Buffer)
  2485.                                 Buffer[0] = 0x1B;
  2486.  
  2487.                             return(0x1B);
  2488.  
  2489.                             /* FS */
  2490.  
  2491.                         case '4':
  2492.                         case '/':
  2493.  
  2494.                             if(Len)
  2495.                                 *Len = 1;
  2496.  
  2497.                             if(Buffer)
  2498.                                 Buffer[0] = 0x1C;
  2499.  
  2500.                             return(0x1C);
  2501.  
  2502.                             /* GS */
  2503.  
  2504.                         case '5':
  2505.                         case ']':
  2506.  
  2507.                             if(Len)
  2508.                                 *Len = 1;
  2509.  
  2510.                             if(Buffer)
  2511.                                 Buffer[0] = 0x1D;
  2512.  
  2513.                             return(0x1D);
  2514.  
  2515.                             /* RS */
  2516.  
  2517.                         case '6':
  2518.                         case '~':
  2519.  
  2520.                             if(Len)
  2521.                                 *Len = 1;
  2522.  
  2523.                             if(Buffer)
  2524.                                 Buffer[0] = 0x1E;
  2525.  
  2526.                             return(0x1E);
  2527.  
  2528.  
  2529.                             /* US */
  2530.  
  2531.                         case '7':
  2532.                         case '?':
  2533.  
  2534.                             if(Len)
  2535.                                 *Len = 1;
  2536.  
  2537.                             if(Buffer)
  2538.                                 Buffer[0] = 0x1F;
  2539.  
  2540.                             return(0x1F);
  2541.                     }
  2542.                 }
  2543.             }
  2544.         }
  2545.  
  2546.             /* Do the final conversion... */
  2547.  
  2548.         if(Actual = ConvertKey(Qualifier,Code,Prev,ConvertBuffer,256))
  2549.         {
  2550.                 /* Are we to swap the backspace and
  2551.                  * delete keys?
  2552.                  */
  2553.  
  2554.             if(Config -> EmulationConfig -> SwapBSDelete)
  2555.             {
  2556.                 register WORD i;
  2557.  
  2558.                 for(i = 0 ; i < Actual ; i++)
  2559.                 {
  2560.                     if(ConvertBuffer[i] == BKS)
  2561.                         ConvertBuffer[i] = DEL;
  2562.                     else
  2563.                     {
  2564.                         if(ConvertBuffer[i] == DEL)
  2565.                             ConvertBuffer[i] = BKS;
  2566.                     }
  2567.                 }
  2568.             }
  2569.  
  2570.                 /* Translated sequence starts
  2571.                  * with a CSI, let's have a look
  2572.                  * at the associated control
  2573.                  * key.
  2574.                  */
  2575.  
  2576.             if(ConvertBuffer[0] == CSI)
  2577.             {
  2578.                 register WORD i;
  2579.  
  2580.                 for(i = 0 ; i < sizeof(SeqLens) ; i++)
  2581.                 {
  2582.                         /* Does it match? */
  2583.  
  2584.                     if(!memcmp(&ConvertBuffer[1],ConversionTable[i] . RawCode,SeqLens[i]))
  2585.                     {
  2586.                             /* Store the length. */
  2587.  
  2588.                         if(Len)
  2589.                             *Len = 1;
  2590.  
  2591.                             /* Store the result. */
  2592.  
  2593.                         if(Buffer)
  2594.                         {
  2595.                             Buffer[0] = ConversionTable[i] . Result;
  2596.                             Buffer[1] = 0;
  2597.                         }
  2598.  
  2599.                         return(ConversionTable[i] . Result);
  2600.                     }
  2601.                 }
  2602.             }
  2603.  
  2604.                 /* Store the number of characters converted. */
  2605.  
  2606.             if(Len)
  2607.                 *Len = Actual;
  2608.  
  2609.                 /* Store the converted characters. */
  2610.  
  2611.             if(Buffer)
  2612.                 memcpy(Buffer,ConvertBuffer,Actual);
  2613.  
  2614.             return(ConvertBuffer[0]);
  2615.         }
  2616.     }
  2617.  
  2618.     return(0);
  2619. }
  2620.  
  2621.     /* KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer):
  2622.      *
  2623.      *    Convert a raw key information according to the
  2624.      *    current keymap settings.
  2625.      */
  2626.  
  2627. UBYTE __regargs
  2628. KeyConvert(struct IntuiMessage *Massage,STRPTR Buffer,LONG *Len)
  2629. {
  2630.         /* Is this really a keyboard event? */
  2631.  
  2632.     if(Massage -> Class == IDCMP_RAWKEY)
  2633.         return(ConvertTheKey(Buffer,Len,Massage -> Code,Massage -> Qualifier,*(ULONG *)Massage -> IAddress));
  2634.     else
  2635.     {
  2636.         if(Buffer)
  2637.             Buffer[0] = 0;
  2638.  
  2639.         if(Len)
  2640.             *Len = 0;
  2641.  
  2642.         return(0);
  2643.     }
  2644. }
  2645.  
  2646.     /* DoBackspace():
  2647.      *
  2648.      *    Special function: perform backspace.
  2649.      */
  2650.  
  2651. BYTE
  2652. DoBackspace()
  2653. {
  2654.     if(CursorX)
  2655.     {
  2656.         WORD DeltaX,MinX;
  2657.  
  2658.         CursorX--;
  2659.  
  2660.             // What backspace mode are we in?
  2661.  
  2662.         switch(Config -> EmulationConfig -> DestructiveBackspace)
  2663.         {
  2664.                 // Do nothing
  2665.  
  2666.             case 0:
  2667.  
  2668.                 RepositionCursor();
  2669.                 break;
  2670.  
  2671.                 // Shift the line to the left
  2672.  
  2673.             case 2:
  2674.  
  2675.                 BackupRender();
  2676.  
  2677.                 RasterEraseCharacters(1);
  2678.  
  2679.                 if(FontScalingRequired)
  2680.                 {
  2681.                     if(CurrentCharWidth == SCALE_NORMAL)
  2682.                     {
  2683.                         DeltaX    = TextFontWidth * 2;
  2684.                         MinX    = MUL_X(CursorX) * 2;
  2685.                     }
  2686.                     else
  2687.                     {
  2688.                         DeltaX    = TextFontWidth / 2;
  2689.                         MinX    = MUL_X(CursorX) / 2;
  2690.                     }
  2691.                 }
  2692.                 else
  2693.                 {
  2694.                     DeltaX    = TextFontWidth;
  2695.                     MinX    = MUL_X(CursorX);
  2696.                 }
  2697.  
  2698.                 ScrollLineEraseCharacters(1);
  2699.  
  2700.                 ScrollLineRaster(RPort,DeltaX,0,MinX,MUL_Y(CursorY),LastPixel,MUL_Y(CursorY + 1) - 1,FALSE);
  2701.  
  2702.                 BackupRender();
  2703.  
  2704.                 RepositionCursor();
  2705.  
  2706.                 break;
  2707.  
  2708.                 // Clear the character below the cursor
  2709.  
  2710.             default:
  2711.  
  2712.                 RepositionCursor();
  2713.  
  2714.                 ObtainSemaphore(RasterSemaphore);
  2715.  
  2716.                 Raster[CursorY * RasterWidth + CursorX] = ' ';
  2717.  
  2718.                 ReleaseSemaphore(RasterSemaphore);
  2719.  
  2720.                 BackupRender();
  2721.  
  2722.                 if(FontScalingRequired)
  2723.                     PrintScaled(" ",1,CurrentFontScale);
  2724.                 else
  2725.                     Text(RPort," ",1);
  2726.  
  2727.                 BackupRender();
  2728.  
  2729.                 break;
  2730.         }
  2731.     }
  2732.  
  2733.     return(FALSE);
  2734. }
  2735.  
  2736.     /* DoBeep():
  2737.      *
  2738.      *    The real interface to the beep routine.
  2739.      */
  2740.  
  2741. BYTE
  2742. DoBeep()
  2743. {
  2744.     BellSignal();
  2745.  
  2746.     return(FALSE);
  2747. }
  2748.  
  2749.     /* DoxON():
  2750.      *
  2751.      *    Perform XON (stop data flow).
  2752.      */
  2753.  
  2754. BYTE
  2755. DoxON()
  2756. {
  2757.         // Commented out, `term' now handles xON locally only
  2758.  
  2759. //    if(Config -> SerialConfig -> xONxOFF)
  2760. //        Status = STATUS_HOLDING;
  2761.  
  2762.     return(FALSE);
  2763. }
  2764.  
  2765.     /* DoLF():
  2766.      *
  2767.      *    Special function: perform line feed.
  2768.      */
  2769.  
  2770. BYTE
  2771. DoLF()
  2772. {
  2773.         // This takes care of regular jump scrolling
  2774.  
  2775.     if(CursorY == Bottom && Bottom > 0 && Config -> EmulationConfig -> MaxJump > 1)
  2776.     {
  2777.         WORD Scroll,TotalLines,OldBack = BackgroundPen;
  2778.  
  2779.         Scroll = Config -> EmulationConfig -> MaxJump;
  2780.  
  2781.             // How tall is the current scroll region?
  2782.  
  2783.         TotalLines = Bottom - Top + 1;
  2784.  
  2785.             // Don't scroll more than the entire screenful
  2786.  
  2787.         if(Scroll > TotalLines)
  2788.             Scroll = TotalLines;
  2789.  
  2790.         if(OldBack)
  2791.         {
  2792.             BackgroundPen = 0;
  2793.  
  2794.             UpdatePens();
  2795.         }
  2796.  
  2797.             // Scroll the region...
  2798.  
  2799.         ScrollRegion(Scroll);
  2800.  
  2801.             // Reposition the cursor
  2802.  
  2803.         if(CursorY > Scroll)
  2804.             CursorY -= Scroll;
  2805.         else
  2806.             CursorY = 0;
  2807.  
  2808.         if(OldBack)
  2809.         {
  2810.             BackgroundPen = OldBack;
  2811.  
  2812.             UpdatePens();
  2813.         }
  2814.     }
  2815.  
  2816.     DownLine();
  2817.  
  2818.     RepositionCursor();
  2819.  
  2820.     return(FALSE);
  2821. }
  2822.  
  2823.     /* DoShiftIn():
  2824.      *
  2825.      *    Special function: Shift into graphics mode
  2826.      */
  2827.  
  2828. BYTE
  2829. DoShiftIn()
  2830. {
  2831.     if(CharMode[1] == TABLE_GFX && GFX)
  2832.         CurrentFont = GFX;
  2833.  
  2834.     if(CharMode[1] == TABLE_ASCII)
  2835.         CurrentFont = TextFont;
  2836.  
  2837.     SetFont(RPort,CurrentFont);
  2838.  
  2839.     ConOutputUpdate();
  2840.  
  2841.     Charset = 1;
  2842.  
  2843.     return(FALSE);
  2844. }
  2845.  
  2846.     /* DoShiftOut():
  2847.      *
  2848.      *    Special function: Shift out of graphics mode
  2849.      */
  2850.  
  2851. BYTE
  2852. DoShiftOut()
  2853. {
  2854.     if(CharMode[0] == TABLE_GFX && GFX)
  2855.         CurrentFont = GFX;
  2856.  
  2857.     if(CharMode[0] == TABLE_ASCII)
  2858.         CurrentFont = TextFont;
  2859.  
  2860.     SetFont(RPort,CurrentFont);
  2861.  
  2862.     ConOutputUpdate();
  2863.  
  2864.     Charset = 0;
  2865.  
  2866.     return(FALSE);
  2867. }
  2868.  
  2869.     /* DoCR_LF():
  2870.      *
  2871.      *    Special function: perform carriage return and line feed.
  2872.      */
  2873.  
  2874. BYTE
  2875. DoCR_LF()
  2876. {
  2877.     CursorX = 0;
  2878.  
  2879.     DownLine();
  2880.  
  2881.     RepositionCursor();
  2882.  
  2883.     return(FALSE);
  2884. }
  2885.  
  2886.     /* DoFF():
  2887.      *
  2888.      *    Special function: perform form feed.
  2889.      */
  2890.  
  2891. BYTE
  2892. DoFF()
  2893. {
  2894.     if(Config -> EmulationConfig -> NewLineMode)
  2895.     {
  2896.         CursorX = 0;
  2897.  
  2898.         DoCR_LF();
  2899.     }
  2900.     else
  2901.     {
  2902.         EraseScreen("2");
  2903.  
  2904.         CursorX = CursorY = 0;
  2905.  
  2906.         RepositionCursor();
  2907.  
  2908.         ConFontScaleUpdate();
  2909.     }
  2910.  
  2911.     return(FALSE);
  2912. }
  2913.  
  2914.     /* DoLF_FF_VT():
  2915.      *
  2916.      *    Special function: handle line feed, form feed and vertical
  2917.      *    tab.
  2918.      */
  2919.  
  2920. BYTE
  2921. DoLF_FF_VT()
  2922. {
  2923.     if(Config -> EmulationConfig -> NewLineMode)
  2924.         DoCR_LF();
  2925.     else
  2926.         DoLF();
  2927.  
  2928.     return(FALSE);
  2929. }
  2930.  
  2931.     /* DoCR():
  2932.      *
  2933.      *    Special function: handle carriage return.
  2934.      */
  2935.  
  2936. BYTE
  2937. DoCR()
  2938. {
  2939.     if(Config -> EmulationConfig -> NewLineMode)
  2940.         DoCR_LF();
  2941.     else
  2942.     {
  2943.         CursorX = 0;
  2944.  
  2945.         RepositionCursor();
  2946.     }
  2947.  
  2948.     return(FALSE);
  2949. }
  2950.  
  2951.     /* DoTab():
  2952.      *
  2953.      *    Special function: handle tab, move cursor to next
  2954.      *    tab stop.
  2955.      */
  2956.  
  2957. BYTE
  2958. DoTab()
  2959. {
  2960.     WORD Column;
  2961.  
  2962.     if(RasterAttr[CursorY] == SCALE_ATTR_NORMAL)
  2963.         Column = LastColumn;
  2964.     else
  2965.         Column = ((LastColumn + 1) / 2) - 1;
  2966.  
  2967.     if(Config -> EmulationConfig -> LineWrap)
  2968.     {
  2969.         if(CursorX >= LastColumn)
  2970.         {
  2971.             CursorX = 0;
  2972.  
  2973.             DownLine();
  2974.         }
  2975.         else
  2976.         {
  2977.             while(CursorX < Column)
  2978.             {
  2979.                 CursorX++;
  2980.  
  2981.                 if(TabStops[CursorX])
  2982.                     break;
  2983.             }
  2984.         }
  2985.     }
  2986.     else
  2987.     {
  2988.         while(CursorX < Column)
  2989.         {
  2990.             CursorX++;
  2991.  
  2992.             if(TabStops[CursorX])
  2993.                 break;
  2994.         }
  2995.     }
  2996.  
  2997.     RepositionCursor();
  2998.  
  2999.     return(FALSE);
  3000. }
  3001.  
  3002.     /* DoEnq():
  3003.      *
  3004.      *    Special function: send answerback message.
  3005.      */
  3006.  
  3007. BYTE
  3008. DoEnq()
  3009. {
  3010.     if(Config -> EmulationConfig -> AnswerBack[0])
  3011.         SerialCommand(Config -> EmulationConfig -> AnswerBack);
  3012.  
  3013.     return(FALSE);
  3014. }
  3015.  
  3016.     /* DoEsc():
  3017.      *
  3018.      *    Start new control sequence.
  3019.      */
  3020.  
  3021. BYTE
  3022. DoEsc()
  3023. {
  3024.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3025.         (* ConDump)("^",1);
  3026.  
  3027.     return(TRUE);
  3028. }
  3029.  
  3030.     /* DoCsi():
  3031.      *
  3032.      *    Start new control sequence.
  3033.      */
  3034.  
  3035. BYTE
  3036. DoCsi()
  3037. {
  3038.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3039.         (* ConDump)("^[",2);
  3040.  
  3041.     ParseCode('[');
  3042.  
  3043.     return(TRUE);
  3044. }
  3045.  
  3046.     /* DoNewEsc(UBYTE Char):
  3047.      *
  3048.      *    Start new control sequence.
  3049.      */
  3050.  
  3051. BYTE
  3052. DoNewEsc(UBYTE Char)
  3053. {
  3054.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3055.         (* ConDump)("^",1);
  3056.  
  3057.     DoCancel();
  3058.  
  3059.     InSequence = TRUE;
  3060.  
  3061.     return(TRUE);
  3062. }
  3063.  
  3064.     /* DoNewCsi(UBYTE Char):
  3065.      *
  3066.      *    Start new control sequence.
  3067.      */
  3068.  
  3069. BYTE
  3070. DoNewCsi(UBYTE Char)
  3071. {
  3072.     if(Config -> TerminalConfig -> EmulationMode == EMULATION_TTY)
  3073.         (* ConDump)("^[",2);
  3074.  
  3075.     DoCancel();
  3076.  
  3077.     InSequence = TRUE;
  3078.  
  3079.     return(ParseCode('['));
  3080. }
  3081.  
  3082. STATIC STRPTR    CR_Translation,
  3083.         LF_Translation;
  3084. STATIC WORD    CR_Trans_Len,
  3085.         LF_Trans_Len;
  3086.  
  3087. STATIC LONG __regargs
  3088. Translate_CR_LF_1(register STRPTR Data,register LONG Size)
  3089. {
  3090.     register STRPTR    String    = Data;
  3091.     register LONG    Count    = 0;
  3092.     register UBYTE    c;
  3093.  
  3094.     while(Size--)
  3095.     {
  3096.         switch(c = *Data++)
  3097.         {
  3098.             case '\r':
  3099.  
  3100.                 if(CR_Trans_Len)
  3101.                 {
  3102.                     *String++ = *CR_Translation;
  3103.  
  3104.                     Count++;
  3105.                 }
  3106.  
  3107.                 break;
  3108.  
  3109.             case '\n':
  3110.  
  3111.                 if(LF_Trans_Len)
  3112.                 {
  3113.                     *String++ = *LF_Translation;
  3114.  
  3115.                     Count++;
  3116.                 }
  3117.  
  3118.                 break;
  3119.  
  3120.             default:
  3121.  
  3122.                 *String++ = c;
  3123.  
  3124.                 Count++;
  3125.  
  3126.                 break;
  3127.         }
  3128.     }
  3129.  
  3130.     return(Count);
  3131. }
  3132.  
  3133. STATIC LONG __regargs
  3134. Translate_CR_LF_2x2(register STRPTR Data,register LONG Size)
  3135. {
  3136.     register STRPTR    String    = Data;
  3137.     register LONG    Count    = 0;
  3138.     register UBYTE    c;
  3139.  
  3140.     /* ALWAYS */
  3141.     {
  3142.         register BOOL GotIt = FALSE;
  3143.         register LONG i;
  3144.  
  3145.         for(i = 0 ; i < Size ; i++)
  3146.         {
  3147.             if(String[i] == '\r' || String[i] == '\n')
  3148.             {
  3149.                 GotIt = TRUE;
  3150.  
  3151.                 break;
  3152.             }
  3153.         }
  3154.  
  3155.         if(GotIt)
  3156.         {
  3157.             CopyMem(Data,StripBuffer,Size);
  3158.  
  3159.             String    = Data;
  3160.             Data    = StripBuffer;
  3161.         }
  3162.         else
  3163.             return(Size);
  3164.     }
  3165.  
  3166.     while(Size--)
  3167.     {
  3168.         switch(c = *Data++)
  3169.         {
  3170.             case '\r':
  3171.  
  3172.                 if(CR_Trans_Len)
  3173.                 {
  3174.                     register WORD i;
  3175.  
  3176.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3177.                     {
  3178.                         *String++ = CR_Translation[i];
  3179.  
  3180.                         Count++;
  3181.                     }
  3182.                 }
  3183.  
  3184.                 break;
  3185.  
  3186.             case '\n':
  3187.  
  3188.                 if(LF_Trans_Len)
  3189.                 {
  3190.                     register WORD i;
  3191.  
  3192.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3193.                     {
  3194.                         *String++ = LF_Translation[i];
  3195.  
  3196.                         Count++;
  3197.                     }
  3198.                 }
  3199.  
  3200.                 break;
  3201.  
  3202.             default:
  3203.  
  3204.                 *String++ = c;
  3205.  
  3206.                 Count++;
  3207.  
  3208.                 break;
  3209.         }
  3210.     }
  3211.  
  3212.     return(Count);
  3213. }
  3214.  
  3215. STATIC LONG __regargs
  3216. Translate_CR_LF_2LF(register STRPTR Data,register LONG Size)
  3217. {
  3218.     register STRPTR    String    = Data;
  3219.     register LONG    Count    = 0;
  3220.     register UBYTE    c;
  3221.  
  3222.     /* ALWAYS */
  3223.     {
  3224.         register BOOL GotIt = FALSE;
  3225.         register LONG i;
  3226.  
  3227.         for(i = 0 ; i < Size ; i++)
  3228.         {
  3229.             if(String[i] == '\n')
  3230.             {
  3231.                 GotIt = TRUE;
  3232.  
  3233.                 break;
  3234.             }
  3235.         }
  3236.  
  3237.         if(GotIt)
  3238.         {
  3239.             CopyMem(Data,StripBuffer,Size);
  3240.  
  3241.             String    = Data;
  3242.             Data    = StripBuffer;
  3243.         }
  3244.         else
  3245.             return(Size);
  3246.     }
  3247.  
  3248.     while(Size--)
  3249.     {
  3250.         switch(c = *Data++)
  3251.         {
  3252.             case '\r':
  3253.  
  3254.                 if(CR_Trans_Len)
  3255.                 {
  3256.                     register WORD i;
  3257.  
  3258.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3259.                     {
  3260.                         *String++ = CR_Translation[i];
  3261.  
  3262.                         Count++;
  3263.                     }
  3264.                 }
  3265.  
  3266.                 break;
  3267.  
  3268.             case '\n':
  3269.  
  3270.                 if(LF_Trans_Len)
  3271.                 {
  3272.                     register WORD i;
  3273.  
  3274.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3275.                     {
  3276.                         *String++ = LF_Translation[i];
  3277.  
  3278.                         Count++;
  3279.                     }
  3280.                 }
  3281.  
  3282.                 break;
  3283.  
  3284.             default:
  3285.  
  3286.                 *String++ = c;
  3287.  
  3288.                 Count++;
  3289.  
  3290.                 break;
  3291.         }
  3292.     }
  3293.  
  3294.     return(Count);
  3295. }
  3296.  
  3297. STATIC LONG __regargs
  3298. Translate_CR_LF_2CR(register STRPTR Data,register LONG Size)
  3299. {
  3300.     register STRPTR    String    = Data;
  3301.     register LONG    Count    = 0;
  3302.     register UBYTE    c;
  3303.  
  3304.     /* ALWAYS */
  3305.     {
  3306.         register BOOL GotIt = FALSE;
  3307.         register LONG i;
  3308.  
  3309.         for(i = 0 ; i < Size ; i++)
  3310.         {
  3311.             if(String[i] == '\r')
  3312.             {
  3313.                 GotIt = TRUE;
  3314.  
  3315.                 break;
  3316.             }
  3317.         }
  3318.  
  3319.         if(GotIt)
  3320.         {
  3321.             CopyMem(Data,StripBuffer,Size);
  3322.  
  3323.             String    = Data;
  3324.             Data    = StripBuffer;
  3325.         }
  3326.         else
  3327.             return(Size);
  3328.     }
  3329.  
  3330.     while(Size--)
  3331.     {
  3332.         switch(c = *Data++)
  3333.         {
  3334.             case '\r':
  3335.  
  3336.                 if(CR_Trans_Len)
  3337.                 {
  3338.                     register WORD i;
  3339.  
  3340.                     for(i = 0 ; i < CR_Trans_Len ; i++)
  3341.                     {
  3342.                         *String++ = CR_Translation[i];
  3343.  
  3344.                         Count++;
  3345.                     }
  3346.                 }
  3347.  
  3348.                 break;
  3349.  
  3350.             case '\n':
  3351.  
  3352.                 if(LF_Trans_Len)
  3353.                 {
  3354.                     register WORD i;
  3355.  
  3356.                     for(i = 0 ; i < LF_Trans_Len ; i++)
  3357.                     {
  3358.                         *String++ = LF_Translation[i];
  3359.  
  3360.                         Count++;
  3361.                     }
  3362.                 }
  3363.  
  3364.                 break;
  3365.  
  3366.             default:
  3367.  
  3368.                 *String++ = c;
  3369.  
  3370.                 Count++;
  3371.  
  3372.                 break;
  3373.         }
  3374.     }
  3375.  
  3376.     return(Count);
  3377. }
  3378.  
  3379. VOID
  3380. Update_CR_LF_Translation()
  3381. {
  3382.     Forbid();
  3383.  
  3384.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CRLF || Config -> TerminalConfig -> ReceiveCR == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_LFCR || Config -> TerminalConfig -> ReceiveLF == EOL_CRLF)
  3385.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize / 2;
  3386.     else
  3387.         SerialBufferSize = Config -> SerialConfig -> SerialBufferSize;
  3388.  
  3389.     switch(Config -> TerminalConfig -> ReceiveCR)
  3390.     {
  3391.         case EOL_IGNORE:
  3392.  
  3393.             CR_Trans_Len = 0;
  3394.             break;
  3395.  
  3396.         case EOL_CR:
  3397.  
  3398.             CR_Trans_Len    = 1;
  3399.             CR_Translation    = "\r";
  3400.             break;
  3401.  
  3402.         case EOL_LF:
  3403.  
  3404.             CR_Trans_Len    = 1;
  3405.             CR_Translation    = "\n";
  3406.             break;
  3407.  
  3408.         case EOL_CRLF:
  3409.  
  3410.             CR_Trans_Len    = 2;
  3411.             CR_Translation    = "\r\n";
  3412.             break;
  3413.  
  3414.         case EOL_LFCR:
  3415.  
  3416.             CR_Trans_Len    = 2;
  3417.             CR_Translation    = "\n\r";
  3418.             break;
  3419.     }
  3420.  
  3421.     switch(Config -> TerminalConfig -> ReceiveLF)
  3422.     {
  3423.         case EOL_IGNORE:
  3424.  
  3425.             LF_Trans_Len = 0;
  3426.             break;
  3427.  
  3428.         case EOL_LF:
  3429.  
  3430.             LF_Trans_Len    = 1;
  3431.             LF_Translation    = "\n";
  3432.             break;
  3433.  
  3434.         case EOL_CR:
  3435.  
  3436.             LF_Trans_Len    = 1;
  3437.             LF_Translation    = "\r";
  3438.             break;
  3439.  
  3440.         case EOL_LFCR:
  3441.  
  3442.             LF_Trans_Len    = 2;
  3443.             LF_Translation    = "\n\r";
  3444.             break;
  3445.  
  3446.         case EOL_CRLF:
  3447.  
  3448.             LF_Trans_Len    = 2;
  3449.             LF_Translation    = "\r\n";
  3450.             break;
  3451.     }
  3452.  
  3453.     if(Config -> TerminalConfig -> ReceiveCR == EOL_CR && Config -> TerminalConfig -> ReceiveLF == EOL_LF)
  3454.         Translate_CR_LF = NULL;
  3455.     else
  3456.     {
  3457.         if(LF_Trans_Len <= 1 && CR_Trans_Len <= 1)
  3458.             Translate_CR_LF = Translate_CR_LF_1;
  3459.         else
  3460.         {
  3461.             if(LF_Trans_Len == 2 && CR_Trans_Len == 2)
  3462.                 Translate_CR_LF = Translate_CR_LF_2x2;
  3463.             else
  3464.             {
  3465.                 if(LF_Trans_Len == 2)
  3466.                     Translate_CR_LF = Translate_CR_LF_2LF;
  3467.                 else
  3468.                 {
  3469.                     if(CR_Trans_Len == 2)
  3470.                         Translate_CR_LF = Translate_CR_LF_2CR;
  3471.                     else
  3472.                         Translate_CR_LF = Translate_CR_LF_1;
  3473.                 }
  3474.             }
  3475.         }
  3476.     }
  3477.  
  3478.     Permit();
  3479. }
  3480.